package com.zbkj.crmeb.store.service.impl;

import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.net.URL;
import java.net.URLConnection;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.constants.WeChatConstants;
import com.factory.PushWarehouseFactory;
import com.taobao.pac.sdk.cp.dataobject.request.MODUAN_ORDER_CREATE.request;
import com.taobao.pac.sdk.cp.dataobject.response.CAINIAO_GLOBAL_GPS_XPO.order;
import com.taobao.pac.sdk.cp.dataobject.response.GLOBAL_SALE_ORDER_NOTIFY.GlobalSaleOrderNotifyResponse;
import com.taobao.pac.sdk.cp.dataobject.response.MODUAN_ORDER_CREATE.response;
import com.utils.*;
import com.utils.jackyun.JackyunOpenHttpUtils;
import com.utils.jackyun.JkyDeliveryOrderConfirmDTO;
import com.utils.lianlianpay.client.LLianPayClient;
import com.utils.lianlianpay.dto.refund.*;
import com.zbkj.crmeb.chant.model.CategoryMatch;
import com.zbkj.crmeb.chant.service.ICategoryMatchService;
import com.zbkj.crmeb.enums.*;
import com.zbkj.crmeb.chant.service.ReserveMoneyDetailService;
import com.zbkj.crmeb.export.vo.DeliveryOrderBatchVo;
import com.zbkj.crmeb.front.response.CustomsPushPayResponse;
import com.zbkj.crmeb.handler.orderconfirm.ByOrderConfirmHandler;
import com.zbkj.crmeb.handler.orderconfirm.OrderConfirmContext;
import com.zbkj.crmeb.handler.orderconfirm.OrderConfirmInterface;
import com.zbkj.crmeb.handler.orderdelivery.ByOrderDeliveryHandler;
import com.zbkj.crmeb.order.channel.ImStoreOrderServiceImpl;
import com.zbkj.crmeb.order.pprocess.LianlianDegreePayOrderProcess;
import com.zbkj.crmeb.order.request.*;
import com.zbkj.crmeb.order.response.JkyOrderResponse;
import com.zbkj.crmeb.plat.by.dto.Result;
import com.zbkj.crmeb.store.dao.PurchaseOrderDao;
import com.zbkj.crmeb.store.dao.StoreOrderInfoDao;
import com.zbkj.crmeb.store.model.*;
import com.zbkj.crmeb.store.request.*;
import com.zbkj.crmeb.store.response.*;
import com.zbkj.crmeb.store.service.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.CommonPage;
import com.common.PageParamRequest;
import com.constants.Constants;
import com.crmeb.core.common.CommonResult;
import com.crmeb.core.exception.CrmebException;
import com.factory.CommonFactory;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import com.google.common.collect.Lists;
import com.seatent.opensdk.api.DeliverGoods;
import com.seatent.opensdk.input.deliverGoods.BatchAddExceptionReplyApiInputDto;
import com.seatent.opensdk.input.deliverGoods.ShippingApiInputDto;
import com.seatent.opensdk.util.HaidaiApiUtils;
import com.utils.adapay.degree.HttpSendResult;
import com.utils.vo.dateLimitUtilVo;
import com.zbkj.crmeb.bill.model.MerFreezeBill;
import com.zbkj.crmeb.bill.service.MerFreezeBillService;
import com.zbkj.crmeb.chant.model.ChannelMemberLevel;
import com.zbkj.crmeb.chant.model.ChannelMerchant;
import com.zbkj.crmeb.chant.model.ChannelMerchantAccount;
import com.zbkj.crmeb.chant.service.IChannelMerchantAccountService;
import com.zbkj.crmeb.chant.service.IChannelMerchantService;
import com.zbkj.crmeb.enums.AccountFlowTypeEnum;
import com.zbkj.crmeb.enums.AreaTypeEnum;
import com.zbkj.crmeb.enums.BarCodeEnum;
import com.zbkj.crmeb.enums.CurrencyEnum;
import com.zbkj.crmeb.enums.ExpressTransition;
import com.zbkj.crmeb.enums.MarkupRateTypeEnum;
import com.zbkj.crmeb.enums.OrderStatusEnum;
import com.zbkj.crmeb.enums.OrderTradeTypeEnum;
import com.zbkj.crmeb.enums.ProcureStatusEnum;
import com.zbkj.crmeb.enums.ProductTypeEnum;
import com.zbkj.crmeb.enums.ReturnReasonEnum;
import com.zbkj.crmeb.enums.StockAreaTempEnum;
import com.zbkj.crmeb.enums.logistics.LogisticsTypeEnum;
import com.zbkj.crmeb.export.vo.StoreOrderExcelVo;
import com.zbkj.crmeb.express.model.Express;
import com.zbkj.crmeb.express.service.ExpressService;
import com.zbkj.crmeb.express.service.LogisticService;
import com.zbkj.crmeb.express.vo.LogisticsResultVo;
import com.zbkj.crmeb.finance.request.FundsMonitorSearchRequest;
import com.zbkj.crmeb.front.vo.OrderAgainVo;
import com.zbkj.crmeb.marketing.model.StoreCouponUser;
import com.zbkj.crmeb.marketing.service.StoreCouponUserService;
import com.zbkj.crmeb.order.AbstractStoreOrderService;
import com.zbkj.crmeb.order.StoreOrderFactory;
import com.zbkj.crmeb.order.oprocess.IOrderProcess;
import com.zbkj.crmeb.order.pprocess.AdapayDegreePayOrderProcess;
import com.zbkj.crmeb.payment.service.OrderPayService;
import com.zbkj.crmeb.store.dao.StoreOrderDao;
import com.zbkj.crmeb.store.model.OrderInfoDelivery;
import com.zbkj.crmeb.store.model.PurchaseGoods;
import com.zbkj.crmeb.store.model.StoreAccountInfo;
import com.zbkj.crmeb.store.model.StoreOrder;
import com.zbkj.crmeb.store.model.StoreOrderCustoms;
import com.zbkj.crmeb.store.model.StoreOrderInfo;
import com.zbkj.crmeb.store.model.StoreOrderInfoPicking;
import com.zbkj.crmeb.store.model.StoreOrderRefundApply;
import com.zbkj.crmeb.store.model.StoreOrderStatus;
import com.zbkj.crmeb.store.model.StoreProduct;
import com.zbkj.crmeb.store.model.StoreProductActive;
import com.zbkj.crmeb.store.model.StoreProductAttrResult;
import com.zbkj.crmeb.store.model.StoreProductAttrValue;
import com.zbkj.crmeb.store.model.Supplier;
import com.zbkj.crmeb.store.utilService.OrderUtils;
import com.zbkj.crmeb.store.vo.StoreOrderInfoVo;
import com.zbkj.crmeb.system.model.SystemAdmin;
import com.zbkj.crmeb.system.model.SystemStore;
import com.zbkj.crmeb.system.model.SystemStoreStaff;
import com.zbkj.crmeb.system.request.SystemWriteOffOrderSearchRequest;
import com.zbkj.crmeb.system.response.StoreOrderItemResponse;
import com.zbkj.crmeb.system.response.SystemWriteOffOrderResponse;
import com.zbkj.crmeb.system.service.SystemAdminService;
import com.zbkj.crmeb.system.service.SystemConfigService;
import com.zbkj.crmeb.system.service.SystemStoreService;
import com.zbkj.crmeb.system.service.SystemStoreStaffService;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.model.UserBill;
import com.zbkj.crmeb.user.model.UserTag;
import com.zbkj.crmeb.user.request.UserOperateFundsRequest;
import com.zbkj.crmeb.user.service.UserBillService;
import com.zbkj.crmeb.user.service.UserService;
import com.zbkj.crmeb.user.service.UserTagService;
import com.zbkj.crmeb.wechat.service.TemplateMessageService;
import com.zbkj.crmeb.wechat.service.WeChatService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
 * @author Mr.Zhang edited by stivepeim
 * @description StoreOrderServiceImpl 接口实现
 * @date 2020-05-28
 */
@Slf4j
@Service
public class StoreOrderServiceImpl extends ServiceImpl<StoreOrderDao, StoreOrder> implements StoreOrderService {
    @Resource
    private StoreOrderDao dao;
    @Autowired
    private SystemStoreService systemStoreService;
    @Autowired
    private RestTemplateUtil restTemplateUtil;
    @Autowired
    private SystemStoreStaffService systemStoreStaffService;
    @Lazy
    @Autowired
    private WeChatService weChatService;
    @Autowired
    private UserService userService;
    @Autowired
    private UserBillService userBillService;
    @Autowired
    private StoreOrderStatusService storeOrderStatusService;
    @Autowired
    private StoreOrderService storeOrderService;
    @Autowired
    private ExpressService expressService;
    @Autowired
    private TemplateMessageService templateMessageService;
    @Autowired
    private LogisticService logisticService;
    @Autowired
    private OrderUtils orderUtils;
    @SuppressWarnings("unused")
	private Page<StoreOrder> pageInfo;
    @Autowired
    private StoreProductService storeProductService;
    @Autowired
    private StoreProductAttrValueService storeProductAttrValueService;
    @Autowired
    private CommonFactory commonFactory;
    @Autowired
    private StoreOrderInfoService storeOrderInfoService;
    @Autowired
    private StoreOrderInfoDao storeOrderInfoDao;
    @Autowired
    private OrderInfoDeliveryService orderInfoDeliveryService;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private IChannelMerchantService channelMerchantService;
    @Autowired
    private ChannelGroupBookingService channelGroupBookingService;
    @Autowired
    private MarkupRateService markupRateService;
    @Autowired
    private StoreAccountInfoService storeAccountInfoService;
    @Autowired
    private PriceUtil priceUtil;
    @Autowired
    private IChannelMerchantAccountService channelMerchantAccountService;
    @Autowired
    private AccountFlowService accountFlowService;
    @Autowired
    private StoreOrderFactory storeOrderFactory;
    @Autowired
    private SystemAdminService systemAdminService;
    @Autowired
    private MerFreezeBillService merFreezeBillService;
    @Autowired
    private StoreProductReplyService storeProductReplyService;
    @Autowired
    PurchaseGoodsService purchaseGoodsService;
    @Autowired
    StoreProductAttrResultService storeProductAttrResultService;
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private StoreOrderCustomsService storeOrderCustomsService;
    @Autowired
    SupplierService supplierService;
    @Autowired
    UserTagService userTagService;
    @Autowired
    StoreCouponUserService storeCouponUserService;
    @Autowired
    StoreOrderTaskService storeOrderTaskService;
    @Autowired
    Redisson redisson;
    @Autowired
    private UserCommissionService userCommissionService;
    @Autowired
    private AdapayDegreePayOrderProcess adapayDegreePayOrderProcess;
    @Autowired
    private LianlianDegreePayOrderProcess lianlianDegreePayOrderProcess;
    @Autowired
    private StoreOrderRefundApplyService storeOrderRefundApplyService;
    @Autowired
    private StoreSaleAnalysisService storeSaleAnalysisService;
    @Autowired
    private IdCardUtils idCardUtils;
    @Autowired
    @Qualifier(value = "commonStoreOrderServiceImpl")
    private CommonStoreOrderService commonStoreOrderService;
    @Autowired
    private CainiaoStoreOrderService cainiaoStoreOrderService;
    @Autowired
    private ImStoreOrderServiceImpl imStoreOrderService;
    @Autowired
    private TraceSourceStoreOrderServiceImpl traceSourceStoreOrderService;
    @Autowired
    private ICategoryMatchService categoryMatchService;
    @Autowired
    private ReserveMoneyDetailService reserveMoneyDetailService;
    @Autowired
    private PushWarehouseFactory pushWarehouseFactory;
    @Resource
    private PurchaseOrderDao purchaseOrderDao;
    @Qualifier("byOrderDeliveryHandler")
    @Autowired
    private OrderConfirmInterface orderConfirmInterface;
    private static final Logger logger = LoggerFactory.getLogger(StoreOrderServiceImpl.class);

    @Value("${message.sendenable}")
    private String sendenable;
    @Value("${order.push.buyer}")
    private boolean buyerPush;
    @Value("${order.push.europe}")
    private boolean europePush;
    @Value("${order.push.vietti}")
    private boolean viettiPush;
    @Value("${order.push.leam}")
    private boolean leamPush;
    @Value("${order.push.bellettini}")
    private boolean bellettiniPush;
    @Value("${order.push.manual}")
    private boolean manualPush;
    @Value("${server.wechat-api-customs-push-url}")
    private String wechatApiCustomsPushUrl;
    @Value("${server.wechatProgramToken}")
    private boolean wechatProgramToken;

    //海带云
    @Value("${seatent.url.login}")
    private String login;
    @Value("${seatent.url.domain}")
    private String domain;
    @Value("${seatent.appKey}")
    private String appKey;
    @Value("${seatent.secret}")
    private String secret;
    @Value("${seatent.username}")
    private String username;
    @Value("${seatent.password}")
    private String password;
    private String accountId = "";
    private String memberId = "";
    private String token = "";

    @Override
    public StoreOrder getByOrderId(String orderId) {
        StoreOrder storeOrderPram = new StoreOrder();
//        storeOrderPram.setUnique(orderUnique);
//        storeOrderPram.setUid(userId);
        storeOrderPram.setOrderId(orderId);
        storeOrderPram.setIsDel(false);
        return getByEntityOne(storeOrderPram);
    }

    /**
     * 批量查询订单
     * @param orderIds
     * @return
     */
    @Override
    public List<StoreOrder> getByOrderIds(List<String> orderIds) {
        QueryWrapper<StoreOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("order_id", orderIds);
        queryWrapper.eq("is_del", false);
        return dao.selectList(queryWrapper);
    }


    /**
     * 列表
     *
     * @param request          请求参数
     * @param pageParamRequest 分页类参数
     * @return List<StoreOrder>
     * @author Mr.Zhang
     * @since 2020-05-28
     */
    @Override
    public StoreOrderResponse getAdminList(StoreOrderSearchRequest request, PageParamRequest pageParamRequest,SystemAdmin systemAdmin) {
        StoreOrderResponse storeOrderResponse = new StoreOrderResponse();
        if (StringUtils.isNotBlank(request.getSuppliersId())) {
            Supplier supplier = supplierService.getById(request.getSuppliersId());
            request.setIsEurope(supplier.getIsEurope());
        }
        //状态数量
        List<StoreOrderInfo> countList = getCount(request,systemAdmin);
        //全部
        List<Integer> all = Stream.of(-2, -1, 0, 1, 2, 4, 5, 6).collect(Collectors.toList());
        Integer count = countList.stream().filter(e -> all.contains(e.getStatus())).map(StoreOrderInfo::getId).reduce(Integer::sum).orElse(0);
        //分组
        Map<Integer, Integer> countMap = countList.stream().filter(e -> e.getStatus() != null).collect(Collectors.toMap(StoreOrderInfo::getStatus, StoreOrderInfo::getId));
        storeOrderResponse.setStatus(
                new StoreOrderCountItemResponse(
                        count, //全部
                        getCountByStatus(countMap, OrderStatusEnum.UNPAID.getCode()), //未支付
                        getCountByStatus(countMap, OrderStatusEnum.NOT_SHIPPED.getCode()), //未发货
                        getCountByStatus(countMap, OrderStatusEnum.SHIPPED.getCode()), //待收货
                        getCountByStatus(countMap, OrderStatusEnum.COMPLETE.getCode()),//交易完成
                        getCountByStatus(countMap, OrderStatusEnum.APPLY_REFUND.getCode()),//退款中
                        getCountByStatus(countMap, OrderStatusEnum.REJECTED_SUCCESS.getCode()),//退货退款
                        getRefundedPartCount(request,systemAdmin),//补偿性退款
                        getCountByStatus(countMap, OrderStatusEnum.CONFIRM.getCode()),//待确认
                        getCountByStatus(countMap, OrderStatusEnum.CANCEL.getCode())//已取消
                )
        );
        //列表数据
        List<StoreOrderItemResponse> storeOrderItemResponseArrayList = new ArrayList<>();
        StoreOrderSearchRequest searchRequest = new StoreOrderSearchRequest();
        BeanUtils.copyProperties(request, searchRequest);
        getStoreOrderListRequest(searchRequest,systemAdmin);
        Page<Object> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        //查询子订单
        List<StoreOrderInfo> childOrderList = dao.selectChildOrderListByUnionQuery(searchRequest);
        if (childOrderList != null && childOrderList.size() > 0) {
            storeOrderItemResponseArrayList = formatChildOrder(childOrderList);
        }
        CommonPage<StoreOrderItemResponse> storeOrderItemResponseCommonPage = CommonPage.restPage(CommonPage.copyPageInfo(page, storeOrderItemResponseArrayList));
        storeOrderResponse.setList(storeOrderItemResponseCommonPage);
        //头部数据
        pageParamRequest.setLimit(1);
        List<StoreOrderInfo> amountList = dao.getSumAllPriceByCondition(searchRequest);
        Map<String, StoreOrderInfo> amountMap = amountList.stream().collect(Collectors.toMap(StoreOrderInfo::getVerifyCode, e -> e));
        BigDecimal payPrice = amountList.stream().map(StoreOrderInfo::getPayPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal deductionPrice = amountList.stream().map(StoreOrderInfo::getDeductionPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        storeOrderResponse.setTop(
                new StoreOrderTopItemResponse(
                        orderUtils.getCurrentCount(request.getStatus(), storeOrderResponse.getStatus()),
                        payPrice.add(deductionPrice),
                        getPayPriceByType(amountMap, Constants.PAY_TYPE_WE_CHAT),
                        getPayPriceByType(amountMap, Constants.PAY_TYPE_YUE),
                        payPrice
                )
        );
        return storeOrderResponse;
    }

    @Override
    public StoreOrderResponse getPickingList(StoreOrderSearchRequest request, PageParamRequest pageParamRequest,SystemAdmin systemAdmin) {
        StoreOrderResponse storeOrderResponse = new StoreOrderResponse();
        if (StringUtils.isNotBlank(request.getSuppliersId())) {
            Supplier supplier = supplierService.getById(request.getSuppliersId());
            request.setIsEurope(supplier.getIsEurope());
        }
        if (request.getPickingType() == null) {
            throw new CrmebException("批采订单类型不能为空");
        }
        List<StoreOrderInfo> storeOrderInfoList = new ArrayList<>();
        List<StoreOrderItemResponse> storeOrderItemResponseArrayList = new ArrayList<>();
        //待核实
        Page<Object> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        if (request.getPickingType() == 1) {
            if (StringUtils.isNotBlank(request.getDateLimit())) {
                dateLimitUtilVo dateLimitUtilVo = DateUtil.getDateLimit(request.getDateLimit());
                request.setStartTime(dateLimitUtilVo.getStartTime());
                request.setEndTime(dateLimitUtilVo.getEndTime());
            }
            List<StoreOrderInfoPicking> infoPickingList = dao.selectVerifyOrderInfoList(request);
            for (StoreOrderInfoPicking infoPicking : infoPickingList) {
                StoreOrderInfo storeOrderInfo = new StoreOrderInfo();
                BeanUtils.copyProperties(infoPicking, storeOrderInfo);
                storeOrderInfo.setIsVirtual(true);
                storeOrderInfoList.add(storeOrderInfo);
            }
        } else if (request.getPickingType() == 2) {
            //已核实
            StoreOrderSearchRequest searchRequest = new StoreOrderSearchRequest();
            BeanUtils.copyProperties(request, searchRequest);
            getStoreOrderListRequest(searchRequest,systemAdmin);
            //查询子订单
            storeOrderInfoList = dao.selectChildOrderListByUnionQuery(searchRequest);
            //状态数量
            List<StoreOrderInfo> countList = getCount(request,systemAdmin);
            //全部
            List<Integer> all = Stream.of(-2, -1, 0, 1, 2, 4, 5, 6).collect(Collectors.toList());
            Integer count = countList.stream().filter(e -> all.contains(e.getStatus())).map(StoreOrderInfo::getId).reduce(Integer::sum).orElse(0);
            //分组
            Map<Integer, Integer> countMap = countList.stream().filter(e -> e.getStatus() != null).collect(Collectors.toMap(StoreOrderInfo::getStatus, StoreOrderInfo::getId));
            storeOrderResponse.setStatus(
                    new StoreOrderCountItemResponse(
                            count, //全部
                            getCountByStatus(countMap, OrderStatusEnum.UNPAID.getCode()), //未支付
                            getCountByStatus(countMap, OrderStatusEnum.NOT_SHIPPED.getCode()), //未发货
                            getCountByStatus(countMap, OrderStatusEnum.SHIPPED.getCode()), //待收货
                            getCountByStatus(countMap, OrderStatusEnum.COMPLETE.getCode()),//交易完成
                            getCountByStatus(countMap, OrderStatusEnum.APPLY_REFUND.getCode()),//退款中
                            getCountByStatus(countMap, OrderStatusEnum.REJECTED_SUCCESS.getCode()),//退货退款
                            getRefundedPartCount(request,systemAdmin),//补偿性退款
                            getCountByStatus(countMap, OrderStatusEnum.CONFIRM.getCode()),//待确认
                            getCountByStatus(countMap, OrderStatusEnum.CANCEL.getCode())//已取消
                    )
            );
            //头部数据
            pageParamRequest.setLimit(1);
            List<StoreOrderInfo> amountList = dao.getSumAllPriceByCondition(searchRequest);
            Map<String, StoreOrderInfo> amountMap = amountList.stream().collect(Collectors.toMap(StoreOrderInfo::getVerifyCode, e -> e));
            BigDecimal payPrice = amountList.stream().map(StoreOrderInfo::getPayPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal deductionPrice = amountList.stream().map(StoreOrderInfo::getDeductionPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            storeOrderResponse.setTop(
                    new StoreOrderTopItemResponse(
                            orderUtils.getCurrentCount(request.getStatus(), storeOrderResponse.getStatus()),
                            payPrice.add(deductionPrice),
                            getPayPriceByType(amountMap, Constants.PAY_TYPE_WE_CHAT),
                            getPayPriceByType(amountMap, Constants.PAY_TYPE_YUE),
                            payPrice
                    )
            );
        } else if (request.getPickingType() == 3) {
            if (StringUtils.isNotBlank(request.getDateLimit())) {
                dateLimitUtilVo dateLimitUtilVo = DateUtil.getDateLimit(request.getDateLimit());
                request.setStartTime(dateLimitUtilVo.getStartTime());
                request.setEndTime(dateLimitUtilVo.getEndTime());
            }
            List<StoreOrderInfoPicking> infoPickingList = dao.selectVerifyOrderInfoList(request);
            for (StoreOrderInfoPicking infoPicking : infoPickingList) {
                StoreOrderInfo storeOrderInfo = new StoreOrderInfo();
                BeanUtils.copyProperties(infoPicking, storeOrderInfo);
                storeOrderInfo.setIsVirtual(true);
                storeOrderInfoList.add(storeOrderInfo);
            }
        }
        if (CollectionUtils.isNotEmpty(storeOrderInfoList)) {
            storeOrderItemResponseArrayList = formatChildOrder(storeOrderInfoList);
        }
        CommonPage<StoreOrderItemResponse> storeOrderItemResponseCommonPage = CommonPage.restPage(CommonPage.copyPageInfo(page, storeOrderItemResponseArrayList));
        storeOrderResponse.setList(storeOrderItemResponseCommonPage);
        return storeOrderResponse;


    }

    private BigDecimal getPayPriceByType(Map<String, StoreOrderInfo> amoutMap, String payType) {
        BigDecimal price = BigDecimal.ZERO;
        StoreOrderInfo storeOrderInfo = amoutMap.get(payType);
        if (storeOrderInfo != null) {
            price = storeOrderInfo.getPayPrice();
        }
        return price;
    }

    private int getRefundedPartCount(StoreOrderSearchRequest request,SystemAdmin systemAdmin) {
        StoreOrderSearchRequest searchRequest = new StoreOrderSearchRequest();
        BeanUtils.copyProperties(request, searchRequest);
        searchRequest.setStatus(Constants.ORDER_STATUS_REFUNDED_PART);
        getStoreOrderListRequest(searchRequest,systemAdmin);
        return dao.getRefundedPartCount(searchRequest);
    }

    private int getCountByStatus(Map<Integer, Integer> countMap, Integer status) {
        Integer count = countMap.get(status);
        return count == null ? 0 : count;
    }

    private List<StoreOrderItemResponse> formatChildOrder(List<StoreOrderInfo> childOrderList) {
        //子订单根据order_id分组查询主订单信息
        Set<Integer> orderIdList = childOrderList.stream().map(StoreOrderInfo::getOrderId).collect(Collectors.toSet());
        List<StoreOrder> storeOrderList = dao.selectList(Wrappers.lambdaQuery(StoreOrder.class).in(StoreOrder::getId, orderIdList).orderByDesc(StoreOrder::getId));
        //下单用户列表
        Set<Integer> userIdList = storeOrderList.stream().map(StoreOrder::getUid).collect(Collectors.toSet());
        List<User> userList = userService.list(Wrappers.lambdaQuery(User.class).in(User::getUid, userIdList));
        //用户标签列表
        Map<Integer, List<UserTagInfo>> tagMap = new HashMap<>();
        //推广人列表
        Map<Integer, User> spreadMap = new HashMap<>();
        //团长列表
        Set<Integer> leaderIdList = storeOrderList.stream().filter(e -> null != e.getLeaderId() && 0 != e.getLeaderId()).map(StoreOrder::getLeaderId).collect(Collectors.toSet());
        Map<Integer, User> leaderMap = new HashMap<>();
        if(CollectionUtils.isNotEmpty(leaderIdList)) {
            List<User> leaderList = userService.list(Wrappers.lambdaQuery(User.class).in(User::getUid, leaderIdList));
            leaderMap = leaderList.stream().collect(Collectors.toMap(User::getUid, e -> e));
        }
        userList.parallelStream().forEach(e -> {
            if (spreadMap.get(e.getUid()) == null) {
                User spread = Optional.ofNullable(userService.getById(e.getSpreadUid())).orElse(new User());
                spreadMap.put(e.getUid(), spread);
            }

            List<UserTagInfo> userTagInfoList;
            if (StringUtils.isNotBlank(e.getTagIds()) && tagMap.get(e.getUid()) == null) {
                List<Integer> tagIdList = Stream.of(e.getTagIds().split(",")).map(Integer::parseInt).collect(Collectors.toList());
                List<UserTag> UserTagList = userTagService.list(Wrappers.lambdaQuery(UserTag.class).in(UserTag::getId, tagIdList));
                userTagInfoList = UserTagList.stream().map(tag -> new UserTagInfo().setTagId(tag.getId()).setTagName(tag.getName())).collect(Collectors.toList());
                tagMap.put(e.getUid(), userTagInfoList);
            }
        });
        Map<Integer, List<StoreOrderInfo>> infoMap = childOrderList.stream().collect(Collectors.groupingBy(StoreOrderInfo::getOrderId));
        List<StoreOrderItemResponse> storeOrderItemResponseArrayList = new ArrayList<>();
        //商户信息
        List<Integer> merIdList = storeOrderList.stream().map(StoreOrder::getMerId).distinct().collect(Collectors.toList());
        List<ChannelMerchant> merchantList = channelMerchantService.list(Wrappers.<ChannelMerchant>lambdaQuery().in(ChannelMerchant::getId, merIdList).select(ChannelMerchant::getId, ChannelMerchant::getChannelName));
        Map<Integer, String> merchantMap = merchantList.stream().collect(Collectors.toMap(ChannelMerchant::getId, ChannelMerchant::getChannelName));
        //商品信息
        List<Integer> productIdList = childOrderList.stream().map(StoreOrderInfo::getProductId).distinct().collect(Collectors.toList());
        List<StoreProduct> productList = storeProductService.list(Wrappers.<StoreProduct>lambdaQuery().in(StoreProduct::getId, productIdList)
                .select(StoreProduct::getId, StoreProduct::getSuppliersId, StoreProduct::getSuppliersName));
        Map<Integer, StoreProduct> productMap = productList.stream().collect(Collectors.toMap(StoreProduct::getId, e -> e));
        //订单物流
        List<Integer> orderInfoIdList = childOrderList.stream().filter(e -> !BooleanUtils.isTrue(e.getIsVirtual())).map(StoreOrderInfo::getId).distinct().collect(Collectors.toList());
        Map<Integer, OrderInfoDelivery> deliveryMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(orderInfoIdList)) {
            List<OrderInfoDelivery> deliveryList = orderInfoDeliveryService.list(Wrappers.<OrderInfoDelivery>lambdaQuery().in(OrderInfoDelivery::getOrderInfoId, orderInfoIdList)
                    .groupBy(OrderInfoDelivery::getOrderInfoId).orderByDesc(OrderInfoDelivery::getCreateTime));
            deliveryMap = deliveryList.stream().collect(Collectors.toMap(OrderInfoDelivery::getOrderInfoId, e -> e));
        }
        //备注
        List<String> childOrderNoList = childOrderList.stream().map(StoreOrderInfo::getChildOrderNumber).distinct().collect(Collectors.toList());
        Map<String, String> noteMap = storeOrderStatusService.getNoteMap(childOrderNoList, Constants.ORDER_PLATFORM_NOTE);
        //采购单信息
        Map<Integer, List<PurchaseGoods>> purchaseGoodsMap = new HashMap<>();
        List<Integer> filterOrderInfoIdList = childOrderList.stream().filter(e -> !BooleanUtils.isTrue(e.getIsVirtual())).filter(e -> !Objects.equals(e.getIsEurope(), ProductTypeEnum.INSIDE.getCode()) && !Objects.equals(e.getAutonomous(), 1)).map(StoreOrderInfo::getId).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(filterOrderInfoIdList)) {
            List<PurchaseGoods> purchaseList = purchaseGoodsService.list(Wrappers.lambdaQuery(PurchaseGoods.class).eq(PurchaseGoods::getPushStatus, 1).eq(PurchaseGoods::getPushType, 0)
                    .in(PurchaseGoods::getStoreOrderInfoId, filterOrderInfoIdList));
            purchaseGoodsMap = purchaseList.stream().collect(Collectors.groupingBy(PurchaseGoods::getStoreOrderInfoId));
        }
        for (StoreOrder storeOrder : storeOrderList) {

            StoreOrderItemResponse storeOrderItemResponse = new StoreOrderItemResponse();
            BeanUtils.copyProperties(storeOrder, storeOrderItemResponse);
            storeOrderItemResponse.setChannelName(merchantMap.get(storeOrder.getMerId()));
            //配送方式
            storeOrderItemResponse.setShippingType(storeOrder.getShippingType());
            //使用积分
            storeOrderItemResponse.setUseIntegral(new BigDecimal(storeOrder.getUseIntegral()));
            //支付方式
            storeOrderItemResponse.setPayTypeStr(getPayType(storeOrder.getPayType()));
            //下单用户
            storeOrderItemResponse.setOrderCreateName(storeOrder.getCreateName());
            //用户信息
            storeOrderItemResponse.setUserTagInfoList(tagMap.get(storeOrder.getUid()));
            if (spreadMap.get(storeOrder.getUid()) != null) {
                storeOrderItemResponse.getSpreadInfo().setId(spreadMap.get(storeOrder.getUid()).getUid());
                storeOrderItemResponse.getSpreadInfo().setName(spreadMap.get(storeOrder.getUid()).getNickname());
            }
            Integer leaderId = storeOrder.getLeaderId();
            if(null != leaderId && 0 != leaderId){
                User leader = leaderMap.get(leaderId);
                if(null != leader) {
                    storeOrderItemResponse.setLeaderId(leader.getUid());
                    storeOrderItemResponse.setLeaderName(leader.getNickname());
                }
            }
            //子订单处理信息
            List<OrderInfoProductResponse> childOrderInfoList = new ArrayList<>();
            List<StoreOrderInfo> orderInfoList = infoMap.get(storeOrder.getId());
            for (StoreOrderInfo storeOrderInfo : orderInfoList) {
                StoreProduct product = productMap.get(storeOrderInfo.getProductId());
                //解析商品详情JSON
                StoreOrderInfoVo infoVo = new StoreOrderInfoVo();
                BeanUtils.copyProperties(storeOrderInfo, infoVo, "info");
                infoVo.setInfo(JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class));
                OrderInfoProductResponse orderInfoProductResponse = new OrderInfoProductResponse();
                if (null != product) {
                    infoVo.getInfo().getProductInfo().setSupplierName(product.getSuppliersName());
                    orderInfoProductResponse.setSuppliersId(product.getSuppliersId());
                    orderInfoProductResponse.setSuppliersName(product.getSuppliersName());

                }
                StoreProductAttrValue attrInfo = infoVo.getInfo().getProductInfo().getAttrInfo();
                orderInfoProductResponse.setSkuId(attrInfo.getSourceSkuId());
                orderInfoProductResponse.setBarCode(attrInfo.getBarCode());
                orderInfoProductResponse.setCost(attrInfo.getCost());
                orderInfoProductResponse.setSourceCost(attrInfo.getSourceCost());
                orderInfoProductResponse.setOtPrice(infoVo.getInfo().getProductInfo().getAttrInfo().getOtPrice());
                orderInfoProductResponse.setOrderInfoId(infoVo.getId());
                orderInfoProductResponse.setProductId(infoVo.getProductId());
                orderInfoProductResponse.setCartNum(infoVo.getNum() == null ? infoVo.getInfo().getCartNum() : infoVo.getNum());
                orderInfoProductResponse.setImage(attrInfo.getImage());
                orderInfoProductResponse.setStoreName(infoVo.getInfo().getProductInfo().getStoreName());
                orderInfoProductResponse.setChildOrderNumber(infoVo.getChildOrderNumber());
                orderInfoProductResponse.setStatus(infoVo.getStatus());
                orderInfoProductResponse.setProductPaidPrice(attrInfo.getProductPaidPrice());
                orderInfoProductResponse.setPaidPrice(attrInfo.getPaidPrice());
                orderInfoProductResponse.setDeductionPrice(attrInfo.getDeductionPrice());
                orderInfoProductResponse.setUseIntegral(attrInfo.getUseIntegral());
                BigDecimal subTotalPrice = attrInfo.getSubTotalPrice() == null ? attrInfo.getPrice().add(attrInfo.getTaxPrice() == null ? BigDecimal.ZERO : attrInfo.getTaxPrice().add(attrInfo.getSecondPrice() == null ? BigDecimal.ZERO : attrInfo.getSecondPrice())) : attrInfo.getSubTotalPrice();
                orderInfoProductResponse.setSubTotalPrice(subTotalPrice);
                //橙子商品设置keyword为itemCode
                String keyword = infoVo.getInfo().getProductInfo().getKeyword();
                if (ProductTypeEnum.ORANGE.getCode().equals(infoVo.getInfo().getProductInfo().getIsEurope())) {
                    StoreProductAttrResult result = storeProductAttrResultService.getByProductId(infoVo.getInfo().getProductId());
                    JSONArray jsonArray = JSONArray.parseArray(result.getResult());
                    for (Object o : jsonArray) {
                        JSONObject jsonObject = JSONObject.parseObject(o.toString());
                        if (Objects.equals(jsonObject.get("sourceSkuId"), infoVo.getInfo().getProductInfo().getAttrInfo().getSourceSkuId())) {
                            keyword = (String) jsonObject.get("skuCode");
                        }
                    }
                }
                orderInfoProductResponse.setKeyword(keyword);
                orderInfoProductResponse.setSuk(infoVo.getInfo().getProductInfo().getAttrInfo().getSuk());
                orderInfoProductResponse.setTempName(StockAreaTempEnum.getByTempId(infoVo.getInfo().getProductInfo().getTempId()).getStockAreaName());
                orderInfoProductResponse.setPrice(infoVo.getInfo().getProductInfo().getAttrInfo().getPrice());
                orderInfoProductResponse.setTotalPrice(infoVo.getInfo().getProductInfo().getAttrInfo().getPrice().multiply(new BigDecimal(infoVo.getInfo().getCartNum())));
                OrderInfoDelivery delivery = deliveryMap.get(infoVo.getId());
                if (!BooleanUtils.isTrue(storeOrderInfo.getIsVirtual())) {
                    orderInfoProductResponse.setDelivery(delivery);
                }
                if (Objects.equals(storeOrderInfo.getIsEurope(), ProductTypeEnum.INSIDE.getCode())) {
                    orderInfoProductResponse.setProcureStatus(ProcureStatusEnum.NO_PROCURE.getType());
                } else if (Objects.equals(storeOrderInfo.getAutonomous(), 1)) {
                    orderInfoProductResponse.setProcureStatus(ProcureStatusEnum.AUTO_PROCURE.getType());
                } else {
                    if (BooleanUtils.isTrue(storeOrderInfo.getIsVirtual())) {
                        orderInfoProductResponse.setProcureStatus(ProcureStatusEnum.FOR_PROCURE.getType());
                    } else {
                        List<PurchaseGoods> purchaseGoodsList = purchaseGoodsMap.get(infoVo.getId());
                        orderInfoProductResponse.setProcureStatus((CollectionUtils.isEmpty(purchaseGoodsList) && delivery == null) ? ProcureStatusEnum.FOR_PROCURE.getType() : ProcureStatusEnum.PROCURE.getType());
                        if (CollectionUtils.isNotEmpty(purchaseGoodsList)) {
                            orderInfoProductResponse.setDeliveryOrderNoList(purchaseGoodsList.stream().map(PurchaseGoods::getChannelOrderSn).collect(Collectors.toList()));
                        }
                    }
                }
                orderInfoProductResponse.setOrderCode(Integer.toString(Integer.parseInt(infoVo.getOrderId() + "" + infoVo.getId()), 36).toUpperCase());
                orderInfoProductResponse.setDeliveryAddress(infoVo.getDeliveryAddress());
                orderInfoProductResponse.setFirstPrice(infoVo.getInfo().getProductInfo().getAttrInfo().getFirstPrice());
                orderInfoProductResponse.setSecondPrice(infoVo.getInfo().getProductInfo().getAttrInfo().getSecondPrice());
                orderInfoProductResponse.setTaxPrice(infoVo.getInfo().getProductInfo().getAttrInfo().getTaxPrice());
                orderInfoProductResponse.setBrandName(infoVo.getInfo().getProductInfo().getBrandName());
                orderInfoProductResponse.setRefundReasonTime(storeOrderInfo.getRefundReasonTime());
                orderInfoProductResponse.setRefundReasonWapImg(storeOrderInfo.getRefundReasonWapImg());
                orderInfoProductResponse.setRefundReasonWapExplain(storeOrderInfo.getRefundReasonWapExplain());
                orderInfoProductResponse.setRefundReasonWap(storeOrderInfo.getRefundReasonWap());
                orderInfoProductResponse.setRefundReason(storeOrderInfo.getRefundReason());
                orderInfoProductResponse.setNote(noteMap.get(storeOrderInfo.getChildOrderNumber()));
                //todo 临时变更 by：包珊珊 永麦->lavita
                if (Objects.equals(orderInfoProductResponse.getSuppliersId(),255)){
                    orderInfoProductResponse.setSuppliersName("lavita");
                }

                orderInfoProductResponse.setIsWzbsc(infoVo.getIsWzbsc());
                childOrderInfoList.add(orderInfoProductResponse);

            }
            storeOrderItemResponse.setChildOrderList(childOrderInfoList);
            storeOrderItemResponseArrayList.add(storeOrderItemResponse);
        }
        return storeOrderItemResponseArrayList;
    }

    public void getStoreOrderListRequest(StoreOrderSearchRequest request,SystemAdmin systemAdmin) {
        request.setMerIds(systemAdminService.getAdminMerIds());
        if (StringUtils.isNotBlank(request.getDateLimit())) {
            dateLimitUtilVo dateLimitUtilVo = DateUtil.getDateLimit(request.getDateLimit());
            request.setStartTime(dateLimitUtilVo.getStartTime());
            request.setEndTime(dateLimitUtilVo.getEndTime());
        }
        String where = " 1=1";
        if (request.getIsPicking() != null) {
            if (request.getIsPicking()) {
                where += " and a.picking_id != 0 ";
            } else {
                where += " and a.picking_id = 0 ";
            }
        }
        if (request.getShippingType() != null) {
            where += " and a.shipping_type  = " + request.getShippingType();
        }
        if (request.getCouponId() != null) {
            where += " and a.coupon_id in (select id from eb_store_coupon_user where coupon_id = " + request.getCouponId() + " ) ";
        }
        if (null != request.getIsPushJky()) {
            if (request.getIsPushJky()) {
                where += " and a.push_jky_status != 0";
            } else {
                where += " and a.push_jky_status = 0";
            }
        }

        //2023.2.16新加检索条件 供应商
        // 分配供应商后忽略商户权限
        if (StringUtils.isNotBlank(systemAdmin.getSupplierIds())){
            List<Integer> supplierIdList = JSONArray.parseArray(systemAdmin.getSupplierIds()).toJavaList(Integer.class);
            if(CollectionUtils.isNotEmpty(supplierIdList)){
                where += " and b.actual_supplier_id in " + supplierIdList.toString().replace("[", "(").replace("]", ")");
                request.setMerId(null).setMerIds(null);
            }
        }


        String status = request.getStatus();
        if (null != status) {
            List<Integer> orderStatusList = new ArrayList<>();
            Integer orderStatus = null; //订单状态
            Integer refundStatus = null; //退款状态
            switch (status) {
                case Constants.ORDER_STATUS_ALL:
                    orderStatusList = Stream.of(0, 1, 2, 4, 5, 6, -1, -2).collect(Collectors.toList());
                    break;
                case Constants.ORDER_STATUS_UNPAID: //未支付
                    orderStatus = 0;
                    break;
                case Constants.ORDER_STATUS_NOT_SHIPPED: //未发货
                    orderStatus = 1;
                    break;
                case Constants.ORDER_STATUS_SPIKE: //待收货
                    orderStatus = 2;
                    break;
                case Constants.ORDER_STATUS_BARGAIN: //待评价
                    orderStatus = 3;
                    break;
                case Constants.ORDER_STATUS_COMPLETE: //交易完成
                    orderStatus = 4;
                    break;
                case Constants.ORDER_STATUS_CANCEL: //取消
                    orderStatus = 5;
                    break;
                case Constants.ORDER_STATUS_REFUNDING: //退款中
                    orderStatus = -1;
                    break;
                case Constants.ORDER_STATUS_REFUNDED: //退货退款
                    orderStatus = -2;
                    break;
                case Constants.ORDER_STATUS_REFUNDED_PART: //补偿性退款
                    refundStatus = 3;
                    break;
                case Constants.ORDER_STATUS_CONFIRM: //待确认
                    orderStatus = OrderStatusEnum.CONFIRM.getCode();
                    break;
                default:
                    //其他传状态不存在的-99
                    orderStatus = -99;
                    break;
            }
            if (CollectionUtils.isNotEmpty(orderStatusList)) {
                where += " and b.status in " + orderStatusList.toString().replace("[", "(").replace("]", ")");
            }

            if (orderStatus != null) {
                where += " and b.status  = " + orderStatus;
            }

            if (refundStatus != null) {
                where += " and b.refund_status  = " + refundStatus;
            }

        }
        request.setWhere(where);
        request.setIsIntegral(request.getIsIntegral());
        if (StringUtils.isNotBlank(request.getCateIdList())) {
            List<String> cateIdList = Arrays.asList(request.getCateIdList().split(","));
            request.setCateIdListSearch(cateIdList);
        }
    }

    /**
     * 分页
     *
     * @param request          StoreOrderSearchRequest 请求参数
     * @param pageParamRequest PageParamRequest 分页
     * @return List<StoreOrder>
     * @author Mr.Zhang
     * @since 2020-06-12
     */
    @Override
    public List<StoreOrder> getList(StoreOrderSearchRequest request, PageParamRequest pageParamRequest) {
        this.pageInfo = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        QueryWrapper<StoreOrder> queryWrapper = new QueryWrapper<>();
        getRequestWhere(queryWrapper, request);
        getStatusWhere(queryWrapper, request.getStatus());
        getIsDelWhere(queryWrapper, false);
        getIsSystemDelWhere(queryWrapper, false);
        queryWrapper.orderByDesc("id");
        return dao.selectList(queryWrapper);
    }

    /**
     * H5 订单列表
     *
     * @param storeOrder       查询参数
     * @param pageParamRequest 分页参数
     * @return 查询结果
     */
    @Override
    public List<StoreOrder> getUserOrderList(StoreOrder storeOrder, PageParamRequest pageParamRequest) {
        this.pageInfo = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        LambdaQueryWrapper<StoreOrder> lqw = new LambdaQueryWrapper<>();
        if (!Objects.isNull(storeOrder.getStatus())) {
            statusApiByWhere(lqw, storeOrder.getStatus());
        }
        if (null != storeOrder.getId()) {
            lqw.eq(StoreOrder::getId, storeOrder.getId());
        }
        if (null != storeOrder.getDeliveryId()) {
            lqw.eq(StoreOrder::getDeliveryId, storeOrder.getDeliveryId());
        }
        if (null != storeOrder.getUnique()) {
            lqw.eq(StoreOrder::getUnique, storeOrder.getUnique());
        }
        if (null != storeOrder.getIsDel()) {
            lqw.eq(StoreOrder::getIsDel, storeOrder.getIsDel());
        }
        if (null != storeOrder.getUid()) {
            lqw.eq(StoreOrder::getUid, storeOrder.getUid());
        }
        if (null != storeOrder.getOrderId()) {
            lqw.eq(StoreOrder::getOrderId, storeOrder.getOrderId());
        }
        if (null != storeOrder.getPayTime()) {
            lqw.eq(StoreOrder::getPayTime, storeOrder.getPayTime());
        }
        if (null != storeOrder.getStoreId()) {
            lqw.eq(StoreOrder::getStoreId, storeOrder.getStoreId());
        }
        if (null != storeOrder.getShippingType()) {
            lqw.eq(StoreOrder::getShippingType, storeOrder.getShippingType());
        }
        if (null != storeOrder.getPayType()) {
            lqw.eq(StoreOrder::getPayType, storeOrder.getPayType());
        }
        if (null != storeOrder.getUidList() && storeOrder.getUidList().size() > 0) {
            lqw.in(StoreOrder::getUid, storeOrder.getUidList());
            lqw.in(StoreOrder::getStatus, 1, 2, 3, 4);
        }
        lqw.orderByDesc(StoreOrder::getCreateTime);
        return dao.selectList(lqw);
    }

    /**
     * 创建订单
     *
     * @param storeOrder 订单参数
     * @return 结果标识
     */
    @Override
    public boolean create(StoreOrder storeOrder) {
        return dao.insert(storeOrder) > 0;
    }

    /**
     * 注意 再次购买的逻辑 orderAgain 存redis 后confirm 接口时 从redis中获取数据再下单 调用orderCreate时 isNew=true 走直接购买逻辑
     *
     * @param userId        用户id
     * @param productId     产品id
     * @param cartNum       商品数量
     * @param orderUnique   商品唯一标识
     * @param type          商品默认类型
     * @param isNew         isNew
     * @param combinationId 拼团id
     * @param skillId       秒杀id
     * @param bargainId     砍价id
     * @return
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Error.class, CrmebException.class})
    public List<String> addCartAgain(Integer userId, Integer productId, Integer cartNum, String orderUnique, String type, boolean isNew, Integer combinationId, Integer skillId, Integer bargainId) {
        List<String> cacheIdsResult = new ArrayList<>();
        // todo 营销活动二期处理

        // 检测订单是否有效
        StoreOrder storeOrderPram = new StoreOrder();
        storeOrderPram.setUnique(orderUnique);
        storeOrderPram.setUid(userId);
        storeOrderPram.setIsDel(false);
        StoreOrder existOrder = getByEntityOne(storeOrderPram);
        if (null == existOrder) throw new CrmebException("订单不存在");
        OrderAgainVo orderAgainVo = orderUtils.tidyOrder(existOrder, true, false);
        Long cacheKey = DateUtil.getTime() + userId;
        List<StoreCartResponse> orderAgainCache = new ArrayList<>();
        ChannelMemberLevel userMemberLevel = userService.getUserMemberLevel(userService.getInfo());
        ChannelMerchant channelMerchant = channelMerchantService.getById(existOrder.getMerId());
        for (StoreOrderInfoVo so : orderAgainVo.getCartInfo()) {
            // 判断商品是否有效
            StoreProduct storeProductPram = new StoreProduct();
            storeProductPram.setId(productId);
            storeProductPram.setIsDel(false);
            storeProductPram.setIsShow(true);
            StoreProduct existProduct = storeProductService.getByEntity(storeProductPram);
            if (null == existProduct) throw new CrmebException("该商品已下架或者删除");

            // 判断商品对应属性是否有效
            StoreProductAttrValue apAttrValuePram = new StoreProductAttrValue();
            apAttrValuePram.setProductId(productId);
            apAttrValuePram.setSourceSkuId(so.getUnique());
            apAttrValuePram.setType(0);
            StoreProductAttrValue existSPAttrValue = storeProductAttrValueService.getByEntity(apAttrValuePram);
            if (null == existSPAttrValue) throw new CrmebException("请选择有效的商品属性");
            if (existSPAttrValue.getStock() < cartNum) throw new CrmebException("该商品库存不足");
            priceUtil.calcProductValuePrice(Collections.singletonList(existSPAttrValue), existOrder.getMerId(), existProduct, AreaTypeEnum.CN.getType(), null, false, null,true,null);
            BigDecimal levelVipUpPrice = null;
            if (userMemberLevel != null && userMemberLevel.getPriceLadder() == 2) {
                levelVipUpPrice = priceUtil.getLevelVipPrice(channelMerchant, userMemberLevel, existSPAttrValue.getCost(), existSPAttrValue.getPrice(), existSPAttrValue.getTaxAndSecondPrice());
            }
            // 添加有效商品至缓存 缓存为购物车对象
            if (isNew) {
                StoreCartResponse storeCartResponse = new StoreCartResponse();
                cacheIdsResult.add(cacheKey + "");
                storeCartResponse.setId(cacheKey);
                storeCartResponse.setType(type);
                storeCartResponse.setProductId(productId);

                storeCartResponse.setProductAttrUnique(so.getUnique());
                storeCartResponse.setCartNum(cartNum);
                StoreProductCartProductInfoResponse spcpInfo = new StoreProductCartProductInfoResponse();
                BeanUtils.copyProperties(existProduct, spcpInfo);
                spcpInfo.setSupplierName(existProduct.getSuppliersName());
                spcpInfo.setAttrInfo(existSPAttrValue);
                storeCartResponse.setProductInfo(spcpInfo);
                storeCartResponse.setTrueStock(storeCartResponse.getProductInfo().getAttrInfo().getStock());
                storeCartResponse.setCostPrice(storeCartResponse.getProductInfo().getAttrInfo().getCost());
//                storeCartResponse.setTruePrice(BigDecimal.ZERO);
                storeCartResponse.setTruePrice(existSPAttrValue.getPrice());
                storeCartResponse.setVipTruePrice(BigDecimal.ZERO);
                storeCartResponse.setSourceCostPrice(existSPAttrValue.getSourceCost());
                storeCartResponse.setPickingId(existOrder.getPickingId());
                storeCartResponse.setPickingProductId(so.getPickingProductId());
                storeCartResponse.setTaxAndSecondPrice(existSPAttrValue.getTaxAndSecondPrice());
                storeCartResponse.setLevelVipUpPrice(levelVipUpPrice);
                storeCartResponse.setMemberLevel(userMemberLevel);
                orderAgainCache.add(storeCartResponse);
            }
        }
        orderUtils.setCacheOrderAgain(cacheKey + "", orderAgainCache);

        return cacheIdsResult;
//        else{ // else 中的逻辑暂时未使用到
//         StoreCart storeCartNewPram = new StoreCart();
//         storeCartNewPram.setUid(userId);
//         storeCartNewPram.setProductId(productId);
//         storeCartNewPram.setCartNum(cartNum);
//         storeCartNewPram.setProductAttrUnique(productAttrUnique);
//         storeCartNewPram.setIsNew(isNew);
//         storeCartNewPram.setType(type);
//         storeCartNewPram.setCombinationId(combinationId);
//         storeCartNewPram.setCreateTime(DateUtil.nowDateTime());
//         storeCartNewPram.setBargainId(bargainId);
//         storeCartNewPram.setSeckillId(skillId);
//         saveCate(storeCartNewPram);
//         return storeCartNewPram;
//        }
    }

    /**
     * 订单基本查询
     *
     * @param storeOrder 订单参数
     * @return 订单查询结果
     */
    @Override
    public List<StoreOrder> getByEntity(StoreOrder storeOrder) {
        LambdaQueryWrapper<StoreOrder> lqw = new LambdaQueryWrapper<>();
        lqw.setEntity(storeOrder);
        return dao.selectList(lqw);
    }

    /**
     * 订单基本查询一条
     *
     * @param storeOrder 参数
     * @return 查询结果
     */
    @Override
    public StoreOrder getByEntityOne(StoreOrder storeOrder) {
        LambdaQueryWrapper<StoreOrder> lqw = new LambdaQueryWrapper<>();
        lqw.setEntity(storeOrder);
        return dao.selectOne(lqw);
    }

    /**
     * 更新订单信息
     *
     * @param storeOrder 更新参数
     * @return 更新结果
     */
    @Override
    public boolean updateByEntity(StoreOrder storeOrder) {
        LambdaUpdateWrapper<StoreOrder> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        if (null != storeOrder.getPayPrice()) {
            lambdaUpdateWrapper.set(StoreOrder::getPayPrice, storeOrder.getPayPrice());
        }
        if (null != storeOrder.getPayType()) {
            lambdaUpdateWrapper.set(StoreOrder::getPayType, storeOrder.getPayType());
        }
        if (null != storeOrder.getVerifyCode()) {
            lambdaUpdateWrapper.set(StoreOrder::getVerifyCode, storeOrder.getVerifyCode());
        }
        if (null != storeOrder.getShippingType()) {
            lambdaUpdateWrapper.set(StoreOrder::getShippingType, storeOrder.getShippingType());
        }
        if (null != storeOrder.getOrderId()) {
            lambdaUpdateWrapper.set(StoreOrder::getOrderId, storeOrder.getOrderId());
        }
        if (null != storeOrder.getIsChannel()) {
            lambdaUpdateWrapper.set(StoreOrder::getIsChannel, storeOrder.getIsChannel());
        }
        if (null != storeOrder.getDeliveryType()) {
            lambdaUpdateWrapper.set(StoreOrder::getDeliveryType, storeOrder.getDeliveryType());
        }
        if (null != storeOrder.getPaid()) {
            lambdaUpdateWrapper.set(StoreOrder::getPaid, storeOrder.getPaid());
        }
        if (null != storeOrder.getStatus()) {
            lambdaUpdateWrapper.set(StoreOrder::getStatus, storeOrder.getStatus());
        }
        if (null != storeOrder.getRefundStatus()) {
            lambdaUpdateWrapper.set(StoreOrder::getRefundStatus, storeOrder.getRefundStatus());
        }
        if (null != storeOrder.getRefundPrice()) {
            lambdaUpdateWrapper.set(StoreOrder::getRefundPrice, storeOrder.getRefundPrice());
        }
        if (null != storeOrder.getUid()) {
            lambdaUpdateWrapper.set(StoreOrder::getUid, storeOrder.getUid());
        }
        if (null != storeOrder.getIsDel()) {
            lambdaUpdateWrapper.set(StoreOrder::getIsDel, storeOrder.getIsDel());
        }
        if (null != storeOrder.getIsSystemDel()) {
            lambdaUpdateWrapper.set(StoreOrder::getIsSystemDel, storeOrder.getIsSystemDel());
        }
        if (null != storeOrder.getStoreId()) {
            lambdaUpdateWrapper.set(StoreOrder::getStoreId, storeOrder.getStoreId());
        }
        if (null != storeOrder.getPayTime()) {
            lambdaUpdateWrapper.set(StoreOrder::getPayTime, storeOrder.getPayTime());
        }
        if (null != storeOrder.getBackParam()) {
            lambdaUpdateWrapper.set(StoreOrder::getBackParam, storeOrder.getBackParam());
        }
        if (null != storeOrder.getOutOrderId()) {
            lambdaUpdateWrapper.set(StoreOrder::getOutOrderId, storeOrder.getOutOrderId());
        }
        if (null != storeOrder.getReceiptVoucher()) {
            lambdaUpdateWrapper.set(StoreOrder::getReceiptVoucher, storeOrder.getReceiptVoucher());
        }
        if (null != storeOrder.getActivityId()) {
            lambdaUpdateWrapper.set(StoreOrder::getActivityId, storeOrder.getActivityId());
            Integer leaderId = channelGroupBookingService.getLeaderIdByActivityId(storeOrder.getActivityId());
            if (leaderId != null && 0 != leaderId) {
                lambdaUpdateWrapper.set(StoreOrder::getLeaderId, leaderId);
            }
        }
        lambdaUpdateWrapper.eq(StoreOrder::getId, storeOrder.getId());
        return update(lambdaUpdateWrapper);
    }

    /**
     * 余额支付
     *
     * @param currentUser 当前用户
     * @return 支付结果
     */
    @Override
    @Transactional(rollbackFor = {Exception.class, Error.class, CrmebException.class})
    public boolean yuePay(StoreOrder storeOrder, User currentUser) {

        //判断账户余额是否足够
        if (currentUser.getNowMoney().compareTo(storeOrder.getPayPrice()) < 0) {
            throw new CrmebException("余额不足");
        }

        //余额支付操作
        boolean updateUserResult = paySuccess(storeOrder, currentUser);

        //余额支付成功之后, 处理事务
        if (updateUserResult) {
            orderPayService.afterPaySuccess(storeOrder);
        }

        return updateUserResult;
    }


    /**
     * 余额支付操作
     *
     * @param storeOrder  当前支付订单
     * @param currentUser 当前用户
     * @return 成功处理结果
     */
    @Transactional(rollbackFor = {RuntimeException.class, Error.class, CrmebException.class})
    public boolean paySuccess(StoreOrder storeOrder, User currentUser) {

        //更新用户的余额
        boolean result = updateUserNowMoney(storeOrder, currentUser);

        //更新用户积分 - 扣减积分
        //更新积分放在afterPaySuccess里
        //updateUserIntegral(storeOrder, currentUser);

        return result;
    }

    /**
     * 余额支付操作 - 更新用户的余额
     */
    public boolean updateUserNowMoney(StoreOrder storeOrder, User currentUser) {
        try {
            BigDecimal priceSubtract = currentUser.getNowMoney().subtract(storeOrder.getPayPrice());
            return userService.updateNowMoney(currentUser.getUid(), priceSubtract);
        } catch (Exception e) {
            throw new CrmebException("余额支付 - 更新用户的余额失败");
        }
    }

    /**
     * 余额支付操作 - 更新用户积分
     *
     * @param storeOrder
     * @param currentUser
     */
    @Override
    public void updateUserIntegral(StoreOrder storeOrder, User currentUser) {
        //是否开启积分
        // TODO DIDIOK Integral
        Integer enableIntegral = channelMerchantService.getById(currentUser.getMerId()).getEnableIntegral();
        if (storeOrder.getUseIntegral() > 0 && enableIntegral == 1) {
            BigDecimal useIntegral = BigDecimal.valueOf(storeOrder.getUseIntegral(), 0);
            currentUser.setIntegral(currentUser.getIntegral().subtract(useIntegral));
            userService.updateBase(currentUser);

            boolean disIntegle = true;

            BigDecimal deductionPrice = storeOrder.getDeductionPrice();
            UserBill userBill = new UserBill();
            userBill.setTitle("积分抵扣");
            userBill.setUid(currentUser.getUid());
            userBill.setCategory("integral");
            userBill.setType("deduction");
            userBill.setNumber(useIntegral);
            userBill.setLinkId(storeOrder.getId() + "");
            userBill.setBalance(currentUser.getIntegral());

            userBill.setMark("创建订单使用" + userBill.getNumber() + "积分抵扣" + deductionPrice + "元");
            boolean userBillSaveResult = userBillService.save(userBill);
            disIntegle = disIntegle && userBillSaveResult;
            if (!disIntegle) {
                throw new CrmebException("使用积分抵扣失败");
            }
        }
        userService.userPayCountPlus(currentUser);
    }

    /**
     * 取消订单回滚积分
     *
     * @param storeOrder
     * @param currentUser
     */

    public void cancelUserIntegral1(StoreOrder storeOrder, User currentUser) {
        //是否开启积分
        Integer enableIntegral = channelMerchantService.getById(currentUser.getMerId()).getEnableIntegral();
        if (storeOrder.getUseIntegral() > 0 && enableIntegral == 1) {
            BigDecimal useIntegral = BigDecimal.valueOf(storeOrder.getUseIntegral(), 0);
            currentUser.setIntegral(currentUser.getIntegral().add(new BigDecimal(storeOrder.getUseIntegral())));
            userService.updateBase(currentUser);

            boolean disIntegle = true;

            UserBill userBill = new UserBill();
            userBill.setTitle("积分返还");
            userBill.setUid(currentUser.getUid());
            userBill.setCategory(Constants.USER_BILL_CATEGORY_INTEGRAL);
            userBill.setType(Constants.USER_BILL_TYPE_GIVE);
            userBill.setNumber(useIntegral);
            userBill.setLinkId(storeOrder.getId() + "");
            userBill.setBalance(currentUser.getIntegral());

            userBill.setMark("取消订单返还" + userBill.getNumber() + "积分");
            boolean userBillSaveResult = userBillService.save(userBill);
            disIntegle = disIntegle && userBillSaveResult;
            if (!disIntegle) {
                throw new CrmebException("积分回滚失败");
            }
        }
        userService.userPayCountPlus(currentUser);
    }

    /**
     * 取消订单回滚积分
     *
     * @param storeOrder
     * @param currentUser
     */
    @Override
    public void cancelUserIntegral(StoreOrder storeOrder, User currentUser, String mesg) {
        FundsMonitorSearchRequest fundsMonitorSearchRequest = new FundsMonitorSearchRequest();
        fundsMonitorSearchRequest.setCategory("integral");
        fundsMonitorSearchRequest.setType("deduction");
        fundsMonitorSearchRequest.setLinkId(storeOrder.getId().toString());
        //fundsMonitorSearchRequest.setPm(1);
        PageParamRequest pageParamRequest = new PageParamRequest();
        pageParamRequest.setLimit(Constants.EXPORT_MAX_LIMIT);
        List<UserBill> list = userBillService.getList(fundsMonitorSearchRequest, pageParamRequest);

        if (null == list || list.size() < 1) {
            return;
        }

        UserBill userBillpay = list.get(0);
        if (currentUser == null || currentUser.getIntegral() == null) {
            return;
        }
        currentUser.setIntegral(currentUser.getIntegral().add(userBillpay.getNumber()));
        userService.updateBase(currentUser);

        UserBill userBill = new UserBill();
        userBill.setTitle("积分返还");
        userBill.setPm(1);
        userBill.setUid(userBillpay.getUid());
        userBill.setCategory(Constants.USER_BILL_CATEGORY_INTEGRAL);
        userBill.setType(Constants.USER_BILL_TYPE_GIVE);
        userBill.setNumber(userBillpay.getNumber());
        userBill.setLinkId(userBillpay.getLinkId());
        userBill.setBalance(currentUser.getIntegral());

        userBill.setMark(mesg + "返还" + userBill.getNumber() + "积分");
        boolean disIntegral = userBillService.save(userBill);
        if (!disIntegral) {
            throw new CrmebException("积分回滚失败");
        }
        userService.userPayCountPlus(currentUser);
    }

    @Override
    public CommonResult<Object> getSupplierOrderInfoById(Integer id) {
        SupplierOrderInfoResponse response = new SupplierOrderInfoResponse();
        PurchaseGoods purchaseGoods = purchaseGoodsService.getById(id);
        if (null == purchaseGoods || StringUtils.isBlank(purchaseGoods.getChannelOrderSn())) {
            return CommonResult.failed("推送记录不存在或渠道订单号为空");
        }
        if (purchaseGoods.getChannelType() == 5) {
            CommonResult<Object> orderInfo = storeOrderFactory.orderInfo(purchaseGoods.getChannelOrderSn(), purchaseGoods.getChannelType());
            if (orderInfo.getCode() != 200) {
                return orderInfo;
            }
            List<String> collect = Stream.of("已发货", "已收货", "已完成", "已取消").collect(Collectors.toList());
            if (collect.contains(orderInfo.getData().toString())) {
                CommonResult<Object> logisticsInfo = storeOrderFactory.getOrderLogisticsInfo(purchaseGoods.getChannelOrderSn(), purchaseGoods.getChannelType());
                if (logisticsInfo.getCode() == 200 && logisticsInfo.getData() != null) {
                    BeanUtils.copyProperties(logisticsInfo.getData(), response);
                }
            }
            response.setOrderStatus((String) orderInfo.getData());
        } else {
            //平台逻辑
            response.setOrderStatus(purchaseGoods.getRefundStatus() == 1 ? OrderStatusEnum.APPLY_REFUND.getMsg() : OrderStatusEnum.valueOf(purchaseGoods.getStatus()).getMsg());
            if (Objects.equals(purchaseGoods.getStatus(), OrderStatusEnum.CANCEL.getCode()) && StringUtils.isNotBlank(purchaseGoods.getCancelReason())) {
                response.setOrderStatus(response.getOrderStatus() + "(" + purchaseGoods.getCancelReason() + ")");
            }
        }
        return CommonResult.success(response);
    }

    /**
     * 子订单确认订单
     * 变更供应商
     * @param id
     * @return
     */
    @Override
    public boolean confirmChildOrder(Integer id, String remark, Integer actualSupplierId, BigDecimal actualCost, BigDecimal actualCostEur, Integer stockAreaCode,SystemAdmin systemAdmin) {
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(id);
        checkStoreOrderInfo(storeOrderInfo);

        storeOrderInfo.setStatus(OrderStatusEnum.NOT_SHIPPED.getCode());
        storeOrderInfo.setActualSupplierId(actualSupplierId);
        storeOrderInfo.setActualCost(actualCost);
        storeOrderInfo.setActualCostEur(actualCostEur);
        storeOrderInfo.setActualStockAreaCode(stockAreaCode);
        String message = Constants.ORDER_LOG_MESSAGE_CONFIRM_SUCCESS;

        if (StringUtils.isNotBlank(remark)) {
            message = message + ",备注：" + remark;
        }

        boolean b = storeOrderInfoService.updateById(storeOrderInfo);
        if (b) {
            Supplier supplier = supplierService.getById(actualSupplierId);
            if (supplier != null) {
                purchaseGoodsService.update(Wrappers.<PurchaseGoods>lambdaUpdate()
                        .set(PurchaseGoods::getStatus, Constants.ORDER_STATUS_H5_NOT_SHIPPED)
                        .set(PurchaseGoods::getGoodsSupplier, supplier.getSuppliersName())
                        .eq(PurchaseGoods::getStoreOrderInfoId, storeOrderInfo.getId())
                        .eq(PurchaseGoods::getStatus, Constants.ORDER_STATUS_H5_CONFIRM));
            }
            //确认订单记录备注
            storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_CONFIRM_SUCCESS, message);
            //查询主订单状态
            StoreOrder storeOrder = getById(storeOrderInfo.getOrderId());
            if (storeOrder.getStatus().equals(OrderStatusEnum.CONFIRM.getCode())) {
                storeOrder.setStatus(OrderStatusEnum.NOT_SHIPPED.getCode());
                updateById(storeOrder);
            }
        }
        return b;
    }

    /**
     * 修改用户地址
     *
     * @param request
     * @return
     */
    @Override
    public boolean updateUserAddress(UpdateUserAddressRequest request) {
        StoreOrder storeOrder = getById(request.getId());
        if (null == storeOrder) {
            throw new CrmebException("该订单不存在");
        }
//        if (!storeOrder.getStatus().equals(OrderStatusEnum.CONFIRM.getCode()) && !storeOrder.getStatus().equals(OrderStatusEnum.UNPAID.getCode()) && !storeOrder.getStatus().equals(OrderStatusEnum.VERIFY.getCode())) {
//            throw new CrmebException("只有待审核，未支付,待确认的订单可以修改");
//        }
        if (storeOrder.getPickingId() > 0 && !request.getAreaType().equals(storeOrder.getAreaType())) {
            throw new CrmebException("区域类型不正确");
        }
        //2c可以修改其他地区的地址，2b只能改为当前地区
        ChannelMerchant channelMerchant = channelMerchantService.getById(storeOrder.getMerId());
        if (Objects.equals(channelMerchant.getAppletType(), 0) && !request.getAreaType().equals(storeOrder.getAreaType())) {
            throw new CrmebException("区域类型不正确");
        }
        if (StringUtils.isNotBlank(request.getIdCard())) {
        	idCardUtils.checkIdCard(request.getRealName(), request.getIdCard());
            storeOrder.setIdCard(request.getIdCard());
        }
        if (storeOrder.getStatus().equals(OrderStatusEnum.CONFIRM.getCode())) {
            boolean flag = false;
            //查询订单商品来源
            List<StoreOrderInfo> list = storeOrderInfoService.list(Wrappers.lambdaQuery(StoreOrderInfo.class).eq(StoreOrderInfo::getOrderId, request.getId()));
            for (StoreOrderInfo storeOrderInfo : list) {
                if (storeOrderInfo.getIsEurope() != 1) {
                    flag = true;
                }
            }
            if (!flag) {
                throw new CrmebException("订单中没有供应商商品");
            }
        }
        BeanUtils.copyProperties(request, storeOrder, "idCard");
        storeOrder.setUserAddress(request.getProvince() + request.getCity() + request.getDistrict() + request.getDetail());
        boolean b = updateById(storeOrder);
        if (b) {
            storeOrderStatusService.createLog(storeOrder.getId(), storeOrder.getOrderId(), "update_address", "后台修改地址");
        }
        return b;
    }

    /**
     * 确认收货（确认完成）
     *
     * @param id     orderInfoId
     * @param reason
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean confirmReceipt(Integer id, String reason) {
        // 快递订单：云仓商品   快递订单；云仓商品——待收货状态
        // 自提订单: 所有类型商品  自提订单：自建商品/云仓商品    ——待发货，待收货状态
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(id);
        if (null == storeOrderInfo) {
            throw new CrmebException("没有找到订单信息");
        }
        if (1 == storeOrderInfo.getAbnormal()) {
            throw new CrmebException("该订单为异常订单");
        }
        StoreOrder storeOrder = getById(storeOrderInfo.getOrderId());
        if (Objects.isNull(storeOrder)) {
            throw new CrmebException("该订单主订单不存在");
        }
        if (1 == storeOrder.getShippingType()) {
            // 快递订单
            if (1 == storeOrderInfo.getIsEurope()) {
                throw new CrmebException("平台只能完成快递类型云仓商品订单");
            }
            if (!storeOrderInfo.getStatus().equals(OrderStatusEnum.SHIPPED.getCode())) {
                throw new CrmebException("该子订单状态不是待收货状态");
            }
        } else {
            // 自提订单
            if (!storeOrderInfo.getStatus().equals(OrderStatusEnum.SHIPPED.getCode())
                    && !storeOrderInfo.getStatus().equals(OrderStatusEnum.NOT_SHIPPED.getCode())) {
                throw new CrmebException("该子订单状态不是待发货/待收货状态");
            }
        }
        //修改子订单状态
        storeOrderInfo.setStatus(Constants.ORDER_STATUS_H5_COMPLETE);
        boolean update = storeOrderInfoService.updateById(storeOrderInfo);
        if (update) {
            //加入分销
            userService.joinDistribution(storeOrder, storeOrderInfo);
            //佣金解冻
            userCommissionService.completeCommission(storeOrderInfo);

            // 连连支付：担保确认
            Map<String, Object> confirmResult = orderUtils.securedConfirm(storeOrder);
            if(CollectionUtils.isEmpty(confirmResult) || null == confirmResult.get("result") || !"SUCCESS".equals(confirmResult.get("result"))){
                String msg = (CollectionUtils.isEmpty(confirmResult) || null == confirmResult.get("result")) ? "空" : confirmResult.get("result").toString();
                log.info("连连支付：担保确认失败，失败原因：{}", msg);
                throw new CrmebException("连连支付：担保确认失败，失败原因：" + msg);
            }
            //供应商完成订单
            Supplier supplier = supplierService.getById(storeOrderInfo.getActualSupplierId());
            if (supplier != null) {
                purchaseGoodsService.update(Wrappers.<PurchaseGoods>lambdaUpdate().set(PurchaseGoods::getStatus, Constants.ORDER_STATUS_H5_SPIKE)
                        .eq(PurchaseGoods::getStoreOrderInfoId, storeOrderInfo.getId()).eq(PurchaseGoods::getStatus, Constants.ORDER_STATUS_H5_COMPLETE)
                        .eq(PurchaseGoods::getGoodsSupplier, supplier.getSuppliersName()));
            }
            log.info("---------------订单:{} 平台确认完成订单--------------------", storeOrderInfo.getChildOrderNumber());
            String message = StringUtils.isNotBlank(reason) ? "平台确认完成订单,备注：" + reason : "平台确认完成订单";
            storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), "confirm_receipt", message);
            //处理总订单状态
            orderUtils.updateOrderStatus(storeOrderInfo.getOrderId());
        }
        return update;
    }

    /**
     * 确认收货（确认完成）
     *
     * @param storeOrderRequest
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean confirmReceiptManually(StoreOrderRequest storeOrderRequest) {
        StoreOrder storeOrder = storeOrderService.getById(storeOrderRequest.getId());

        if (Objects.isNull(storeOrder)) {
            throw new CrmebException("该订单主订单不存在");
        }
        Integer orderId = storeOrderRequest.getId();
        // 快递订单：云仓商品   快递订单；云仓商品——待收货状态
        // 自提订单: 所有类型商品  自提订单：自建商品/云仓商品    ——待发货，待收货状态
        LambdaQueryWrapper<StoreOrderInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StoreOrderInfo::getOrderId, orderId);
        List<StoreOrderInfo> storeOrderInfoList = storeOrderInfoDao.selectList(lambdaQueryWrapper);

        if(CollectionUtils.isEmpty(storeOrderInfoList)){
            throw new CrmebException("没有找到订单信息!!!");
        }
        for(StoreOrderInfo storeOrderInfo : storeOrderInfoList) {
            if (null == storeOrderInfo) {
                throw new CrmebException("没有找到订单信息");
            }
            if(null != storeOrderInfo.getStatus() && storeOrderInfo.getStatus() == Constants.ORDER_STATUS_H5_COMPLETE ){
                continue;
            }
            //修改子订单状态
            storeOrderInfo.setStatus(Constants.ORDER_STATUS_H5_COMPLETE);
            boolean update = storeOrderInfoService.updateById(storeOrderInfo);
            if (update) {
                try {
                    //加入分销
                    userService.joinDistribution(storeOrder, storeOrderInfo);
                }catch (Exception e){
                    log.error("加入分销失败，{}", e.fillInStackTrace());
                }
                try {
                    //供应商完成订单
                    Supplier supplier = supplierService.getById(storeOrderInfo.getActualSupplierId());
                    if (supplier != null) {
                        purchaseGoodsService.update(Wrappers.<PurchaseGoods>lambdaUpdate().set(PurchaseGoods::getStatus, Constants.ORDER_STATUS_H5_SPIKE)
                                .eq(PurchaseGoods::getStoreOrderInfoId, storeOrderInfo.getId()).eq(PurchaseGoods::getStatus, Constants.ORDER_STATUS_H5_COMPLETE)
                                .eq(PurchaseGoods::getGoodsSupplier, supplier.getSuppliersName()));
                    }
                }catch (Exception e){
                    log.error("供应商完成订单失败，{}", e.fillInStackTrace());
                }

                //佣金解冻
                userCommissionService.completeCommission(storeOrderInfo);

                // 连连支付：担保确认
                Map<String, Object> confirmResult = orderUtils.securedConfirm(storeOrder);
                if(CollectionUtils.isEmpty(confirmResult) || null == confirmResult.get("result") || !"SUCCESS".equals(confirmResult.get("result"))){
                    String msg = (CollectionUtils.isEmpty(confirmResult) || null == confirmResult.get("result")) ? "空" : confirmResult.get("result").toString();
                    log.info("连连支付：担保确认失败，失败原因：{}", msg);
                    throw new CrmebException("连连支付：担保确认失败，失败原因：" + msg);
                }
                log.info("---------------订单:{} 手动确认完成订单--------------------", storeOrderInfo.getChildOrderNumber());
                SystemAdmin systemAdmin = systemAdminService.getInfo();
                String message = systemAdmin.getAccount() + "：手动将订单状态转为已完成，原状态：" + OrderStatusEnum.valueOf(storeOrderInfo.getStatus()).getMsg();
                storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), "confirm_receipt", message);
                //处理总订单状态
                orderUtils.updateOrderStatus(storeOrderInfo.getOrderId());

            }
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancel(Integer id) {
        StoreOrder storeOrder = getById(id);
        if (null == storeOrder) {
            throw new CrmebException("没有找到相关订单信息!");
        }
        if (!storeOrder.getStatus().equals(OrderStatusEnum.UNPAID.getCode()) && !storeOrder.getStatus().equals(OrderStatusEnum.VERIFY.getCode())) {
            throw new CrmebException("订单状态异常");
        }
        storeOrderStatusService.createLog(storeOrder.getId(), storeOrder.getOrderId(), "cancel_order", "平台取消订单");
        //取消订单返还
        cancelUserIntegral(storeOrder, userService.getById(storeOrder.getUid()), "平台取消订单");
        //取消前状态
        Integer status = storeOrder.getStatus();
        //已取消
        storeOrder.setStatus(OrderStatusEnum.CANCEL.getCode());
        //回滚使用积分
        if (storeOrder.getUseIntegral() > 0) {
            storeOrder.setBackIntegral(storeOrder.getUseIntegral());
            storeOrder.setUseIntegral(0);
        }
        boolean update = updateById(storeOrder);
        //回滚优惠券
        storeCouponUserService.rollbackByCancelOrder(storeOrder);
        if (update && !Objects.equals(status, OrderStatusEnum.VERIFY.getCode())) {
            //取消子订单
            storeOrderInfoService.update(Wrappers.lambdaUpdate(StoreOrderInfo.class).eq(StoreOrderInfo::getOrderId, storeOrder.getId())
                    .set(StoreOrderInfo::getStatus, OrderStatusEnum.CANCEL.getCode()));
            storeOrderTaskService.rollbackStock(storeOrder);
        }
        return update;
    }

    @Override
    public List<StoreOrder> userAndOrderInfoList(QueryWrapper<StoreOrder> queryWrapper) {
        return dao.userAndOrderInfoList(queryWrapper);
    }

    /**
     * 添加运税费
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addActualTaxAndSecondPrice(StoreOrderInfoTaxPriceRequest request) {
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(request.getId());
        if (storeOrderInfo == null) {
            throw new CrmebException("该子订单不存在");
        }
        StoreOrderInfo updateOrderInfo = new StoreOrderInfo();
        updateOrderInfo.setId(request.getId());
        updateOrderInfo.setTaxInlandDeliveryPrice(storeOrderInfo.getTaxInlandDeliveryPrice());
        String message = "填写物流费用（";
        if (Objects.nonNull(request.getTaxInternationalPrice())) {
            updateOrderInfo.setTaxInternationalPrice(request.getTaxInternationalPrice());
            message += "国际运费：" + request.getTaxInternationalPrice();
        }
        if (Objects.nonNull(request.getTaxTurnInlandPrice())) {
            updateOrderInfo.setTaxTurnInlandPrice(request.getTaxTurnInlandPrice());
            message += "，转国内运费：" + request.getTaxTurnInlandPrice();
        }
        if (Objects.nonNull(request.getTaxInlandDeliveryPrice())) {
            updateOrderInfo.setTaxInlandDeliveryPrice(request.getTaxInlandDeliveryPrice());
            message += "，国内配送费：" + request.getTaxInlandDeliveryPrice();
        }
        if (Objects.nonNull(request.getTaxTaxesPrice())) {
            updateOrderInfo.setTaxTaxesPrice(request.getTaxTaxesPrice());
            message += "，税金：" + request.getTaxTaxesPrice();
        }
        boolean b = storeOrderInfoService.updateById(updateOrderInfo);
        message = message.replace("（，", "（") + "）";
        if (StringUtils.isNotBlank(request.getRemark())) {
            message = message + "，备注：" + request.getRemark();
        }
        if (b) {
            storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_UPDATE_TAX_AND_FREIGHT, message);
        }
        return b;
    }

    /**
     * 核销列表
     *
     * @param request          请求参数
     * @param pageParamRequest 分页类参数
     * @return List<StoreOrder>
     * @author Mr.Zhang
     * @since 2020-05-28
     */
    @Override
    public SystemWriteOffOrderResponse getWriteOffList(SystemWriteOffOrderSearchRequest request, PageParamRequest pageParamRequest) {
        LambdaQueryWrapper<StoreOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        String where = " is_del = 0";
//        String where = " is_del = 0 and paid = 1";
        //时间
        if (!StringUtils.isBlank(request.getData())) {
            dateLimitUtilVo dateLimit = DateUtil.getDateLimit(request.getData());
            where += " and (create_time between '" + dateLimit.getStartTime() + "' and '" + dateLimit.getEndTime() + "' )";
        }

        if (!StringUtils.isBlank(request.getKeywords())) {
            where += " and (real_name like '% " + request.getKeywords() + " %' or user_phone = '" + request.getKeywords() + "' or order_id = '" + request.getKeywords() + "' or id = '" + request.getKeywords() + "' )";
        }

        if (request.getStoreId() != null && request.getStoreId() > 0) {
            where += " and store_id = " + request.getStoreId();
        }

        SystemWriteOffOrderResponse systemWriteOffOrderResponse = new SystemWriteOffOrderResponse();
        BigDecimal totalPrice = dao.getTotalPrice(where);
        BigDecimal price = new BigDecimal(BigInteger.ZERO);
        if (totalPrice == null) {
            totalPrice = price;
        }
        systemWriteOffOrderResponse.setOrderTotalPrice(totalPrice);   //订单总金额

        BigDecimal refundPrice = dao.getRefundPrice(where);
        if (refundPrice == null) {
            refundPrice = price;
        }
        systemWriteOffOrderResponse.setRefundTotalPrice(refundPrice); //退款总金额
        systemWriteOffOrderResponse.setRefundTotal(dao.getRefundTotal(where));  //退款总单数


        Page<StoreOrder> storeOrderPage = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());

        lambdaQueryWrapper.apply(where);
        lambdaQueryWrapper.eq(StoreOrder::getRefundStatus, 0);
        lambdaQueryWrapper.orderByDesc(StoreOrder::getId);
        List<StoreOrder> storeOrderList = dao.selectList(lambdaQueryWrapper);

        if (storeOrderList.size() < 1) {
            systemWriteOffOrderResponse.setList(CommonPage.restPage(new PageInfo<>()));
            return systemWriteOffOrderResponse;
        }

        List<StoreOrderItemResponse> storeOrderItemResponseArrayList = formatOrder(storeOrderList);

        systemWriteOffOrderResponse.setTotal(storeOrderPage.getTotal()); //总单数
        systemWriteOffOrderResponse.setList(CommonPage.restPage(CommonPage.copyPageInfo(storeOrderPage, storeOrderItemResponseArrayList)));

        return systemWriteOffOrderResponse;
    }

    /**
     * 格式化订单信息，对外输出一致
     *
     * @param storeOrderList List<StoreOrder> 订单列表
     * @return List<StoreOrderItemResponse>
     * @author Mr.Zhang
     * @since 2020-05-28
     */
    private List<StoreOrderItemResponse> formatOrder(List<StoreOrder> storeOrderList) {
        List<StoreOrderItemResponse> storeOrderItemResponseArrayList = new ArrayList<>();
        if (null == storeOrderList || storeOrderList.size() < 1) {
            return storeOrderItemResponseArrayList;
        }
        //门店id
        List<Integer> storeIdList = storeOrderList.stream().map(StoreOrder::getStoreId).distinct().collect(Collectors.toList());
        //店员id
        List<Integer> clerkIdList = storeOrderList.stream().map(StoreOrder::getClerkId).distinct().collect(Collectors.toList());

        //订单id集合
        List<Integer> orderIdList = storeOrderList.stream().map(StoreOrder::getId).distinct().collect(Collectors.toList());

        //获取门店map
        HashMap<Integer, SystemStore> systemStoreList = systemStoreService.getMapInId(storeIdList);
        //获取店员map
        HashMap<Integer, SystemStoreStaff> systemStoreStaffList = systemStoreStaffService.getMapInId(clerkIdList);
        //获取订单详情map
        HashMap<Integer, List<StoreOrderInfoVo>> orderInfoList = storeOrderInfoService.getMapInId(orderIdList);

        //根据用户获取推广人信息
        List<Integer> userIdList = storeOrderList.stream().map(StoreOrder::getUid).distinct().collect(Collectors.toList());
        //订单用户信息
        HashMap<Integer, User> userList = userService.getMapListInUid(userIdList);

        //推广信息
        HashMap<Integer, User> mapListInUid = new HashMap<>();
        if (userIdList.size() > 0) {
            //推广人信息
            List<Integer> userServiceSpreadPeopleIdList = userService.getSpreadPeopleIdList(userIdList);
            if (userServiceSpreadPeopleIdList.size() > 0) {
                mapListInUid = userService.getMapListInUid(userServiceSpreadPeopleIdList);
            }
        }

        for (StoreOrder storeOrder : storeOrderList) {
            StoreOrderItemResponse storeOrderItemResponse = new StoreOrderItemResponse();
            BeanUtils.copyProperties(storeOrder, storeOrderItemResponse);
            ChannelMerchant channelMerchant = channelMerchantService.getById(storeOrder.getMerId());
            if (null != channelMerchant) {
                storeOrderItemResponse.setChannelName(channelMerchant.getChannelName());
            }
            String storeName = "";
            if (systemStoreList.containsKey(storeOrder.getStoreId())) {
                storeName = systemStoreList.get(storeOrder.getStoreId()).getName();
            }
            storeOrderItemResponse.setStoreName(storeName);

            String clerkName = "";
            if (systemStoreStaffList.containsKey(storeOrder.getClerkId())) {
                clerkName = systemStoreStaffList.get(storeOrder.getClerkId()).getStaffName();
            }
            storeOrderItemResponse.setProductList(orderInfoList.get(storeOrder.getId()));

            //配送方式
            storeOrderItemResponse.setShippingType(storeOrder.getShippingType());
            //订单状态
            storeOrderItemResponse.setStatus(storeOrder.getStatus());
            //订单状态描述
            storeOrderItemResponse.setStatusStr(getStatus(storeOrder));
            //使用积分
            storeOrderItemResponse.setUseIntegral(new BigDecimal(storeOrder.getUseIntegral()));
            //支付方式
            storeOrderItemResponse.setPayTypeStr(getPayType(storeOrder.getPayType()));

            //下单用户
            storeOrderItemResponse.setOrderCreateName(storeOrder.getCreateName());

            //推广人信息
            if (!userList.isEmpty() && userList.containsKey(storeOrder.getUid()) && !mapListInUid.isEmpty()) {
                if (userList.containsKey(storeOrder.getUid()) && mapListInUid.containsKey(userList.get(storeOrder.getUid()).getUid())) {
                    storeOrderItemResponse.getSpreadInfo().setId(mapListInUid.get(userList.get(storeOrder.getUid()).getUid()).getUid());
                    storeOrderItemResponse.getSpreadInfo().setName(mapListInUid.get(userList.get(storeOrder.getUid()).getUid()).getNickname());
                }
            }

            storeOrderItemResponse.setClerkName(clerkName);
            storeOrderItemResponseArrayList.add(storeOrderItemResponse);

        }
        return storeOrderItemResponseArrayList;
    }

    /**
     * 累计消费
     *
     * @param userId Integer 用户id
     * @return UserBalanceResponse
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    @Override
    public BigDecimal getSumBigDecimal(Integer userId, String date) {
        QueryWrapper<StoreOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(pay_price) as pay_price").
                eq("paid", 1).
                eq("is_del", 0);
        if (null != userId) {
            queryWrapper.eq("uid", userId);
        }
        if (null != date) {
            dateLimitUtilVo dateLimit = DateUtil.getDateLimit(date);
            queryWrapper.between("create_time", dateLimit.getStartTime(), dateLimit.getEndTime());
        }
        StoreOrder storeOrder = dao.selectOne(queryWrapper);
        if (null == storeOrder || null == storeOrder.getPayPrice()) {
            return BigDecimal.ZERO;
        }
        return storeOrder.getPayPrice();
    }

    /**
     * 订单列表返回map
     *
     * @param orderIdList Integer 订单id
     * @return UserBalanceResponse
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    @Override
    public Map<Integer, StoreOrder> getMapInId(List<Integer> orderIdList) {
        Map<Integer, StoreOrder> map = new HashMap<>();
        if (null == orderIdList || orderIdList.size() < 1) {
            return map;
        }
        LambdaQueryWrapper<StoreOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(StoreOrder::getId, orderIdList);
        List<StoreOrder> orderList = dao.selectList(lambdaQueryWrapper);

        if (null == orderList || orderList.size() < 1) {
            return map;
        }

        for (StoreOrder storeOrder : orderList) {
            map.put(storeOrder.getId(), storeOrder);
        }
        return map;
    }

    /**
     * 获取订单数量
     *
     * @param userId 用户id
     * @param date   字符串月份 moth
     * @return 对应时间段的订单数量
     */
    @Override
    public int getOrderCount(Integer userId, String date) {
        LambdaQueryWrapper<StoreOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StoreOrder::getPaid, 1)
                .eq(StoreOrder::getIsDel, 0);

        if (null != userId) {
            lambdaQueryWrapper.eq(StoreOrder::getUid, userId);
        }
        if (StringUtils.isNotBlank(date)) {
            dateLimitUtilVo dateLimit = DateUtil.getDateLimit(date);
            lambdaQueryWrapper.between(StoreOrder::getCreateTime, dateLimit.getStartTime(), dateLimit.getEndTime());
        }
        return dao.selectCount(lambdaQueryWrapper);
    }

    /**
     * 按开始结束时间分组订单
     *
     * @param date    String 时间范围
     * @param lefTime int 截取创建时间长度
     * @return HashMap<String, Object>
     * @author Mr.Zhang
     * @since 2020-05-16
     */
    @Override
    public List<StoreOrder> getOrderGroupByDate(String date, int lefTime) {
        QueryWrapper<StoreOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(pay_price) as pay_price", "left(create_time, " + lefTime + ") as orderId", "count(id) as id");
        if (StringUtils.isNotBlank(date)) {
            dateLimitUtilVo dateLimit = DateUtil.getDateLimit(date);
            queryWrapper.between("create_time", dateLimit.getStartTime(), dateLimit.getEndTime());
        }
        queryWrapper.eq("paid", 1);
        queryWrapper.groupBy("orderId").orderByAsc("orderId");
        return dao.selectList(queryWrapper);
    }

    /**
     * 退款
     *
     * @param request StoreOrderRefundRequest 退款参数
     * @return boolean
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Error.class, CrmebException.class})
    public boolean refund(StoreOrderRefundRequest request) {
        String lockKey = "child_order_id:" + request.getOrderId();
        RLock rLock = redisson.getLock(lockKey);
        try {
            if (!rLock.tryLock()) {
                throw new CrmebException("该订单正在退款中!");
            }
            StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(request.getOrderId());
            if (null == storeOrderInfo) {
                throw new CrmebException("未查到订单");
            }
            if (OrderStatusEnum.REJECTED_SUCCESS.getCode().equals(storeOrderInfo.getStatus())) {
                throw new CrmebException("该订单已退货退款!");
            }
            StoreOrder storeOrder = this.getById(storeOrderInfo.getOrderId());
            if (null == storeOrder) {
                throw new CrmebException("未查到订单");
            }

            // 获取支付渠道
            Integer type = orderUtils.getOrderPayType(storeOrder.getMerId()).getCode();
            IOrderProcess orderProcess = commonFactory.getOrderType(type);
            boolean refund = orderProcess.refund(request);
            //记录商品退款数量 author: duyb

            if (refund) {
                saveRefundNumber(storeOrderInfo.getProductId(), storeOrder.getMerId(), request.getAmount());
            }

            return refund;
        } finally {
            if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
                rLock.unlock();
            }
        }
    }

    /**
     * 退款
     *
     * @param request StoreOrderRefundRequest 退款参数
     * @return boolean
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Error.class, CrmebException.class})
    public boolean refundTest(StoreOrderRefundRequest request) {
        String lockKey = "child_order_id:" + request.getOrderId();
        RLock rLock = redisson.getLock(lockKey);
        try {
            if (!rLock.tryLock()) {
                throw new CrmebException("该订单正在退款中!");
            }
            StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(request.getOrderId());
            if (null == storeOrderInfo) {
                throw new CrmebException("未查到订单");
            }

            StoreOrder storeOrder = this.getById(storeOrderInfo.getOrderId());
            if (null == storeOrder) {
                throw new CrmebException("未查到订单");
            }


            // 回调地址
            String domain = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN);
            // 组装参数
            MorePayeeRefundParams params = getBasicRefundParams(request, storeOrder, storeOrderInfo);

            params.setNotify_url(domain + WeChatConstants.PAY_NOTIFY_API_URI_LIANLIAN_DEGREE_REFUND);

            log.info("--------------- 连连聚合支付退款原始数据: {}", JSON.toJSONString(params));
            LLianPayClient lLianPayClient = new LLianPayClient();
            String resultJsonStr = lLianPayClient.sendRequest("https://accpapi.lianlianpay.com/v1/txn/more-payee-refund", JSON.toJSONString(params));
            MorePayeeRefundResult morePayeeRefundResult = JSON.parseObject(resultJsonStr, MorePayeeRefundResult.class);
//
            log.info("--------------- 连连聚合支付退款返回结果源数据: {}", JSON.toJSONString(morePayeeRefundResult));

            return true;
        } finally {
            if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
                rLock.unlock();
            }
        }
    }

    /**
     * 组装参数
     * @return
     */
    private MorePayeeRefundParams getBasicRefundParams(StoreOrderRefundRequest request, StoreOrder storeOrder, StoreOrderInfo storeOrderInfo) {

        MorePayeeRefundParams params = new MorePayeeRefundParams();
        String timestamp = LLianPayDateUtils.getTimestamp();
        params.setTimestamp(timestamp);
        // TODO OID_PARTNER_TEST
        params.setOid_partner(Constants.OID_PARTNER_PROD_TUGOU);
        // 原交易付款方user_id
        params.setUser_id(storeOrder.getUid() == null ? null : String.valueOf(storeOrder.getUid()));

        LocalDateTime time = LocalDateTime.now();
        // 原商户订单信息
        OriginalOrderInfo originalOrderInfo = new OriginalOrderInfo();
        // 原支付交易商户系统唯一交易流水号
        originalOrderInfo.setTxn_seqno(storeOrder.getOrderId());
        // 订单总金额
        originalOrderInfo.setTotal_amount(storeOrder.getPayPrice());
        params.setOriginalOrderInfo(originalOrderInfo);

        // 退款订单信息
        RefundOrderInfo refundOrderInfo = new RefundOrderInfo();
        // 退款订单号。标识一次退款请求，商户系统需要保证唯一
        refundOrderInfo.setRefund_seqno(storeOrder.getOrderId() + time.getHour() + "" + time.getMinute() + "" + time.getSecond());
        refundOrderInfo.setRefund_time(timestamp);
        // 退款总金额。本次需要退款的金额，不允许超过对应原收款方的收款金额
        refundOrderInfo.setRefund_amount(request.getAmount());
        params.setRefundOrderInfo(refundOrderInfo);

        // 原收款方退款信息
        PyeeRefundInfo pyeeRefundInfo = new PyeeRefundInfo();
        // 原收款方id，本次退款需要处理的原交易收款方id
        pyeeRefundInfo.setPayee_id(Constants.OID_PARTNER_PROD_TUGOU);
        /*
        原收款方类型。
        用户：USER
        平台商户：MERCHANT
         */
        pyeeRefundInfo.setPayee_type("MERCHANT");
        /*
        原收款方账户类型。
        用户账户：USEROWN
        平台商户自有资金账户：MCHOWN
        平台商户担保账户：MCHASSURE
        平台商户优惠券账户：MCHCOUPON
        平台商户手续费账户：MCHFEE
         */
        // TODO 平台商户自有资金账户：MCHOWN
        pyeeRefundInfo.setPayee_accttype("MCHOWN");
        // 退款金额。本次需要退款的金额，不允许超过对应原收款方的收款金额。
        pyeeRefundInfo.setPayee_refund_amount(request.getAmount());
        // 垫资标识。当原收款方金额不足时，是否由平台垫资的标识，默认:N
        pyeeRefundInfo.setIs_advance_pay("N");
        params.setPyeeRefundInfos(Arrays.asList(new PyeeRefundInfo[]{pyeeRefundInfo}));

        // 原付款方式退款规则信息
        RefundMethod refundMethod = new RefundMethod();
        // 付款方式
        refundMethod.setMethod("WECHAT_APP_WXA");
        // 退款金额
        refundMethod.setAmount(request.getAmount());
        params.setRefundMethods(Arrays.asList(new RefundMethod[]{refundMethod}));

        return params;
    }

    /**
     * 记录商品退款数量
     *
     * @param productId 商品id merId 商户id amount 退款金额
     * @author duyb
     * @since 2020-10-21
     */
    private void saveRefundNumber(Integer productId, Integer merId, BigDecimal amount) {
        StoreProduct storeProduct = storeProductService.getById(productId);
        StoreProductActive storeProductActive = storeSaleAnalysisService.getOne(Wrappers.<StoreProductActive>lambdaQuery()
                .eq(StoreProductActive::getMerId, merId)
                .eq(StoreProductActive::getProductId, productId)
                .eq(StoreProductActive::getStatisticsDate, DateUtil.nowDateTimeReturnDate("yyyy-MM-dd"))
        );
        if (storeProductActive == null) {
            storeProductActive = new StoreProductActive();
            storeProductActive.setMerId(merId);
            storeProductActive.setProductId(productId);
            storeProductActive.setStoreName(storeProduct.getStoreName());
            storeProductActive.setRefundNumber(1);
            storeProductActive.setRefundAmount(amount);
            storeProductActive.setStatisticsDate(DateUtil.nowDateTimeReturnDate("yyyy-MM-dd"));
        } else {
            storeProductActive.setRefundNumber(storeProductActive.getRefundNumber() + 1);
            storeProductActive.setRefundAmount(storeProductActive.getRefundAmount().add(amount));
        }
        storeSaleAnalysisService.saveOrUpdate(storeProductActive);
    }


    @Override
    public boolean refundGoods(RefundGoodsRequest request) {
        //退货逻辑
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(request.getInfoId());
        if (null == storeOrderInfo) {
            throw new CrmebException("没有找到订单信息");
        }
        if (storeOrderInfo.getRefundStatus() != 1 && storeOrderInfo.getStatus() != -1) {
            throw new CrmebException("该订单不是申请退款状态");
        }
        StoreOrderRefundApply refundApply = storeOrderRefundApplyService.getOne(Wrappers.<StoreOrderRefundApply>lambdaQuery()
                .eq(StoreOrderRefundApply::getInfoId, request.getInfoId())
                .orderByDesc(StoreOrderRefundApply::getId).last("LIMIT 1"));
        if (null == refundApply) {
            throw new CrmebException("订单申请退款记录不存在");
        }
        if (refundApply.getProcessType() != null) {
            throw new CrmebException("该订单已处理");
        }
        refundApply.setProcessType(1);
        refundApply.setProcessTime(new Date());
        refundApply.setReturnConsignee(request.getReturnConsignee());
        refundApply.setReturnPhone(request.getReturnPhone());
        refundApply.setReturnAddress(request.getReturnAddress());
        storeOrderRefundApplyService.updateById(refundApply);
        //退货状态
        storeOrderInfo.setRefundStatus(4);
        storeOrderInfoService.updateById(storeOrderInfo);
        storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_LOG_REFUND_GOODS, "同意退货");
        return true;
    }

    /**
     * 订单手动推送
     */
    @Override
    public Boolean pushOrder(PushOrderRequest pushOrderRequest, String ip, SystemAdmin systemAdmin) {
    	if(!manualPush) {
            throw new CrmebException("当前环境订单手动推送未开启!");
    	}
        // 商品和订单详情
        StoreOrderInfo info = storeOrderInfoService.getById(pushOrderRequest.getInfoId());
        /*StoreProductAttrValue value = storeProductAttrValueService.getOne(Wrappers.<StoreProductAttrValue>lambdaQuery()
                .eq(StoreProductAttrValue::getSourceSkuId, pushOrderRequest.getSourceSkuId())
                .eq(StoreProductAttrValue::getBarCode, pushOrderRequest.getBarCode())
                .last("LIMIT 1")
        );*/
        StoreProductAttrValue value = storeProductAttrValueService.getById(pushOrderRequest.getAttrId());
        if (null == info || null == value) {
            throw new CrmebException("订单或商品为空!");
        }
        if (info.getStatus() != 6) {
            throw new CrmebException("该订单不是待确认状态!");
        }
        if (Objects.equals(info.getAutonomous(), 1)) {
            throw new CrmebException("该订单商户自主发货!");
        }
        if (StringUtil.isEmpty(value.getBarCode())) {
            throw new CrmebException("商品所属供应商异常!");
        }
        // 订单信息
        StoreOrder order = this.getById(info.getOrderId());
        StoreProduct product = storeProductService.getById(value.getProductId());
        if (null == order) {
            throw new CrmebException("订单不存在!");
        }
        if(null != order.getOrderId() && order.getOrderId().startsWith("DY")){
            order.setRealName("***");
            order.setPayName("***");
        }
        //手动推送订单原始商品不校验库存
        StoreCartResponse storeCartResponse = JSON.parseObject(info.getInfo(), StoreCartResponse.class);
        StoreProductAttrValue attrInfo = storeCartResponse.getProductInfo().getAttrInfo();
        //判断是否推送成功过
        int count = purchaseGoodsService.count(Wrappers.<PurchaseGoods>lambdaQuery()
                .eq(PurchaseGoods::getPushStatus, 1)
                .ne(PurchaseGoods::getPushType, 2)
                .eq(PurchaseGoods::getStoreOrderInfoId, info.getId())
                .eq(PurchaseGoods::getGoodsId, value.getProductId())
                .eq(PurchaseGoods::getSkuId, value.getSourceSkuId())
                .ne(PurchaseGoods::getStatus, -2)
        );
        if (count > 0) {
            throw new CrmebException("该订单商品已推送,请勿重复推送此商品!");
        }
        boolean checkStock = Objects.equals(pushOrderRequest.getSourceSkuId(), attrInfo.getSourceSkuId()) && Objects.equals(pushOrderRequest.getBarCode(), attrInfo.getBarCode());
        if (!checkStock) {
            if (pushOrderRequest.getStock() > value.getStock()) {
                throw new CrmebException("商品库存不足!");
            }
        }
        CommonResult<Object> status = this.pushOrder(order, getBarCodeEnum(value.getBarCode(),product.getSuppliersId()), info, pushOrderRequest.getStock(), value, product, ip, systemAdmin, checkStock, pushOrderRequest.getPlatformAddressId());

        if(status.getCode() == 200){
            return true;
        }else {
            throw new CrmebException(status.getMessage());
        }
    }

    private BarCodeEnum getBarCodeEnum(String barCode, Integer suppliersId) {
        // 易磊供应商单独处理
        if (suppliersId == 275 ){
            return BarCodeEnum.CROSSEASY;
        }else if (suppliersId == 244){
            return BarCodeEnum.EASY;
        }else{
            return BarCodeEnum.valueStringOf(barCode);
        }
    }

    /**
     * 订单手动推送至吉客云
     */
    @Override
    public Boolean pushOrderJky(Integer orderId, String ip, SystemAdmin systemAdmin) {
        log.info("--------------- 总后台商户订单推送至吉客云, 订单号: {} ---------------", orderId);

        StoreOrder storeOrder = storeOrderService.getById(orderId);
        List<StoreOrderInfo> orderInfoList = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery().eq(StoreOrderInfo::getOrderId, storeOrder.getId()));
        if (orderInfoList.size() < 1) {
            return false;
        }
        List<StoreOrderInfoVo> storeOrderInfoVoList = new ArrayList<>();
        for (StoreOrderInfo storeOrderInfo : orderInfoList) {
            StoreProduct product = Optional.ofNullable(storeProductService.getOne(Wrappers.lambdaQuery(StoreProduct.class)
                    .eq(StoreProduct::getId, storeOrderInfo.getProductId()))
            ).orElse(new StoreProduct());
            if (ProductTypeEnum.JKY == ProductTypeEnum.valueOf(product.getIsEurope())) {
                throw new CrmebException("订单内商品不能是诚品供应商的!");
            }

            //解析商品详情JSON
            StoreOrderInfoVo storeOrderInfoVo = new StoreOrderInfoVo();
            BeanUtils.copyProperties(storeOrderInfo, storeOrderInfoVo, "info");
            storeOrderInfoVo.setInfo(JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class));
            storeOrderInfoVo.getInfo().setIsReply(
                    storeProductReplyService.isReply(storeOrderInfoVo.getUnique(), "product", storeOrderInfoVo.getOrderId()).size()
            );
            storeOrderInfoVo.getInfo().getProductInfo().setSupplierName(product.getSuppliersName());
            storeOrderInfoVo.getInfo().getProductInfo().setIp(ip);
            storeOrderInfoVo.getInfo().getProductInfo().setUserName(systemAdmin.getRealName());
            storeOrderInfoVo.getInfo().getProductInfo().setUserId(systemAdmin.getId());
            storeOrderInfoVoList.add(storeOrderInfoVo);
        }
        AbstractStoreOrderService storeOrderService = storeOrderFactory.getStoreOrderService(BarCodeEnum.JKY);
        CommonResult<Object> status = storeOrderService.addChannelOrder(storeOrder, storeOrderInfoVoList);
        if(status.getCode() != 200){
            throw new CrmebException(status.getMessage());
        }

        return true;
    }
    
    /**
     * 订单手动推送至温州保税仓
     */
    @Override
    public Boolean pushOrderWzbsc(List<KaiCangOrderRequest> kaiCangOrderRequest) {
    	if(!wechatProgramToken) {
            throw new CrmebException("当前环境不支持该操作!");
    	}
    	log.info("--------------- 总后台商户订单推送至温州保税仓, 订单号: {} ---------------", JSON.toJSONString(kaiCangOrderRequest));
    	
    	List<Integer> infoIds = kaiCangOrderRequest.stream().map(obj -> obj.getInfoId()).collect(Collectors.toList());
    	// 查询订单相关信息
        List<StoreOrderInfo> infos = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
                .in(StoreOrderInfo::getId, infoIds)
                .eq(StoreOrderInfo::getIsWzbsc, false)
        );
        //TODO
        if (CollectionUtils.isEmpty(infos)) {
            throw new CrmebException("订单已推送过保税仓，请联系技术人员!!");
        }
        int orderId = infos.get(0).getOrderId();
        StoreOrder storeOrder = this.getById(orderId);
        if (null == storeOrder) {
            throw new CrmebException("没有查询到订单信息!");
        }
        // 校验子订单是否全部推送
        if (!validateAllSubOrderPush(storeOrder,infos.size())){
            throw new CrmebException("请勾选全部全部子订单再推送!");
        }


//        int count = storeOrderCustomsService.count(Wrappers.<StoreOrderCustoms>lambdaQuery()
//                .eq(StoreOrderCustoms::getOrderNo, storeOrder.getOrderId())
//                .eq(StoreOrderCustoms::getPayTransactionId, storeOrder.getOutOrderId())
//        );
//        if (0 >= count) {
//            throw new CrmebException("请先将商品报关后再推送!");
//        }
        Integer supplierId = null;
    	List<StoreOrderInfoVo> storeOrderInfoVoList = new ArrayList<>();
        Map<Integer, StoreOrderInfo> orderInfoMap = new HashMap<>();
        for (StoreOrderInfo storeOrderInfo : infos) {
            orderInfoMap.put(storeOrderInfo.getId(), storeOrderInfo);
    		StoreProduct product = Optional.ofNullable(storeProductService.getOne(Wrappers.lambdaQuery(StoreProduct.class)
    				.eq(StoreProduct::getId, storeOrderInfo.getProductId()))
    				).orElse(new StoreProduct());
    		
    		//解析商品详情JSON
    		StoreOrderInfoVo storeOrderInfoVo = new StoreOrderInfoVo();
    		BeanUtils.copyProperties(storeOrderInfo, storeOrderInfoVo, "info");
    		storeOrderInfoVo.setInfo(JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class));
    		storeOrderInfoVo.getInfo().setIsReply(
    				storeProductReplyService.isReply(storeOrderInfoVo.getUnique(), "product", storeOrderInfoVo.getOrderId()).size()
    				);
    		storeOrderInfoVo.getInfo().getProductInfo().setSupplierName(product.getSuppliersName());
    		
    		// 设置第三方商品编码
    		for(KaiCangOrderRequest request : kaiCangOrderRequest) {
    			if(request.getInfoId().intValue() == storeOrderInfo.getId().intValue()) {
    				storeOrderInfoVo.getInfo().getProductInfo().setBarCode(request.getProductCode());
    			}
    		}
            if (null == supplierId){
                supplierId = storeOrderInfo.getSuppliersId();
            }
            if (!Objects.equals(storeOrderInfo.getSuppliersId(),supplierId)){
                supplierId = 99999;
            }
    		storeOrderInfoVoList.add(storeOrderInfoVo);
    	}
        String type = kaiCangOrderRequest.get(0).getType();
        // 推送保税仓
        CommonStoreOrderService serviceInstance = null;
        if (StringUtils.isNotBlank(kaiCangOrderRequest.get(0).getWarehouseName())){
            serviceInstance = pushWarehouseFactory.getServiceInstance(kaiCangOrderRequest.get(0).getWarehouseName());
        }else {
            serviceInstance = pushWarehouseFactory.getServiceInstance(supplierId, type);
        }
        // 设置物流code
        if (StringUtils.isNotBlank(kaiCangOrderRequest.get(0).getExpressCode())){
            storeOrder.addFeature("expressCode",kaiCangOrderRequest.get(0).getExpressCode());
        }
        CommonResult result = serviceInstance.pushOrder(storeOrder, storeOrderInfoVoList);
        String pushStoreCode = StoreCodeEnum.COMMON.getCode();
        if (Objects.equals(type,"9610")){
            pushStoreCode = StoreCodeEnum.DIRECT.getCode();
        }
        // 改变子订单状态
    	if(result.getCode() == 200) {
            for (Integer infoId : infoIds) {
                StoreOrderInfo storeOrderInfo = orderInfoMap.get(infoId);
                if (null == storeOrderInfo){
                    continue;
                }
                storeOrderInfo.addFeature("customsType",type);
                storeOrderInfoService.update(Wrappers.<StoreOrderInfo>lambdaUpdate()
                        .eq(StoreOrderInfo::getId, infoId)
                        .set(StoreOrderInfo::getIsWzbsc, true)
                        .set(StoreOrderInfo::getPushStoreCode,pushStoreCode)
                        .set(StoreOrderInfo::getFeature,storeOrderInfo.getFeature())
                );
            }
//    		storeOrderInfoService.update(Wrappers.<StoreOrderInfo>lambdaUpdate()
//                    .in(StoreOrderInfo::getId, infoIds)
//                    .set(StoreOrderInfo::getIsWzbsc, true)
//                    .set(StoreOrderInfo::getPushStoreCode,StoreCodeEnum.COMMON.getCode())
//            );
            return true;
    	}else{
            throw new CrmebException(result.getMessage());
        }

    }

    private boolean validateAllSubOrderPush(StoreOrder storeOrder, int size) {
        if (null == storeOrder){
            return false;
        }
        List<StoreOrderInfo> infos = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
                .in(StoreOrderInfo::getOrderId, storeOrder.getId())
                .eq(StoreOrderInfo::getIsWzbsc, false)
        );
        if (CollectionUtils.isEmpty(infos)){
            return false;
        }
        return infos.size() == size;
    }

    /**
     * 订单手动推送至菜鸟中心仓
     */
    @Override
    public Boolean pushOrderCainiao(List<CainiaoOrderRequest> orderRequest) {
    	if(!wechatProgramToken) {
            throw new CrmebException("当前环境不支持该操作!");
    	}
    	log.info("--------------- 总后台商户订单推送至菜鸟中心仓, 订单号: {} ---------------", JSON.toJSONString(orderRequest));
    	
    	List<Integer> infoIds = orderRequest.stream().map(obj -> obj.getInfoId()).collect(Collectors.toList());
    	// 查询订单相关信息
    	List<StoreOrderInfo> infos = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
    			.in(StoreOrderInfo::getId, infoIds)
    			.eq(StoreOrderInfo::getIsCainiao, false)
    			);
    	if (CollectionUtils.isEmpty(infos)) {
    		throw new CrmebException("订单信息丢失!!");
    	}
    	int orderId = infos.get(0).getOrderId();
    	StoreOrder storeOrder = this.getById(orderId);
    	if (null == storeOrder) {
    		throw new CrmebException("订单已推送过，请联系技术人员!");
    	}
    	
    	List<StoreOrderInfoVo> storeOrderInfoVoList = new ArrayList<>();
    	for (StoreOrderInfo storeOrderInfo : infos) {
            // 退款了的不推送到菜鸟订单仓
            if (storeOrderInfo.getRefundStatus() == 2 || storeOrderInfo.getRefundStatus() == 3) {
                continue;
            }
    		StoreProduct product = Optional.ofNullable(storeProductService.getOne(Wrappers.lambdaQuery(StoreProduct.class)
    				.eq(StoreProduct::getId, storeOrderInfo.getProductId()))
    				).orElse(new StoreProduct());
    		
    		//解析商品详情JSON
    		StoreOrderInfoVo storeOrderInfoVo = new StoreOrderInfoVo();
    		BeanUtils.copyProperties(storeOrderInfo, storeOrderInfoVo, "info");
    		storeOrderInfoVo.setInfo(JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class));
    		storeOrderInfoVo.getInfo().setIsReply(
    				storeProductReplyService.isReply(storeOrderInfoVo.getUnique(), "product", storeOrderInfoVo.getOrderId()).size()
    				);
    		storeOrderInfoVo.getInfo().getProductInfo().setSupplierName(product.getSuppliersName());
    		
    		// 设置第三方商品编码
    		for(CainiaoOrderRequest request : orderRequest) {
    			if(request.getInfoId().intValue() == storeOrderInfo.getId().intValue()) {
    				storeOrderInfoVo.getInfo().getProductInfo().setBarCode(request.getProductCode());
    			}
    		}
    		storeOrderInfoVoList.add(storeOrderInfoVo);
    	}
    	// 推送保税仓
        GlobalSaleOrderNotifyResponse response = cainiaoStoreOrderService.pushOrder(storeOrder, storeOrderInfoVoList);
    	// 改变子订单状态
    	if(response.isSuccess()) {
    		storeOrderInfoService.update(Wrappers.<StoreOrderInfo>lambdaUpdate()
    				.in(StoreOrderInfo::getId, infoIds)
    				.set(StoreOrderInfo::getIsCainiao, true)
                    .set(StoreOrderInfo::getCnOrderCode, response.getCnOrderCode())
    				);
    	}else{
            throw new CrmebException(response.getErrorMsg());
        }
    	
    	return response.isSuccess();
    }

    /**
     * 订单详情
     *
     * @param id Integer 订单id
     * @return StoreOrderItemResponse
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    @Override
    public StoreOrderInfoResponse info(Integer id) {
        StoreOrderInfoResponse storeOrderInfoResponse = new StoreOrderInfoResponse();
        Map<String, Object> discountInfo = new HashMap<>();
        StoreOrder storeOrder = getInfoException(id);
        if (null != storeOrder.getMerId() && 0 != storeOrder.getMerId()) {
            ChannelMerchant channelMerchant = channelMerchantService.getById(storeOrder.getMerId());
            if (null != channelMerchant) {
                storeOrderInfoResponse.setMerPhone(channelMerchant.getContactPhone());
                storeOrderInfoResponse.setMerName(channelMerchant.getChannelName());
                storeOrderInfoResponse.setAppletType(channelMerchant.getAppletType());
            }
        }

        BeanUtils.copyProperties(storeOrder, storeOrderInfoResponse);
        //优惠券名称
        StoreCouponUser storeCouponUser = Optional.ofNullable(storeCouponUserService.getById(storeOrder.getCouponId())).orElse(new StoreCouponUser());
        storeOrderInfoResponse.setCouponName(storeCouponUser.getName());
        storeOrderInfoResponse.setPayTypeStr(getPayType(storeOrder.getPayType()));
        storeOrderInfoResponse.setStatusStr(getStatus(storeOrder));
        //下单用户
        storeOrderInfoResponse.setOrderCreateName(storeOrder.getCreateName());
        //用户信息
        User user = userService.getById(storeOrder.getUid());
        if (null != user){
            List<UserTagInfo> userTagInfoList = new ArrayList<>();
            if (StringUtils.isNotBlank(user.getTagIds())) {
                List<Integer> tagIdList = Stream.of(user.getTagIds().split(",")).map(Integer::parseInt).collect(Collectors.toList());
                List<UserTag> UserTagList = userTagService.list(Wrappers.lambdaQuery(UserTag.class).in(UserTag::getId, tagIdList));
                userTagInfoList = UserTagList.stream().map(tag -> new UserTagInfo().setTagId(tag.getId()).setTagName(tag.getName())).collect(Collectors.toList());
            }
            storeOrderInfoResponse.setUserTagInfoList(userTagInfoList);
            User spread = userService.getById(user.getSpreadUid());
            if (spread != null) {
                storeOrderInfoResponse.getSpreadInfo().setId(spread.getUid());
                storeOrderInfoResponse.getSpreadInfo().setName(spread.getNickname());
            }
            storeOrderInfoResponse.setUser(user);
        }
        storeOrderInfoResponse.setUseIntegral(BigDecimal.valueOf(Optional.ofNullable(storeOrder.getUseIntegral()).orElse(0)));
        storeOrderInfoResponse.setGainIntegral(BigDecimal.valueOf(Optional.ofNullable(storeOrder.getGainIntegral()).orElse(0)));
        storeOrderInfoResponse.setBackIntegral(BigDecimal.valueOf(Optional.ofNullable(storeOrder.getBackIntegral()).orElse(0)));

        // 报关信息
        int count = storeOrderCustomsService.count(Wrappers.<StoreOrderCustoms>lambdaQuery()
                .eq(StoreOrderCustoms::getOrderNo, storeOrder.getOrderId())
                .eq(StoreOrderCustoms::getPayTransactionId, storeOrder.getOutOrderId())
        );

        List<StoreOrderInfoVo> orderInfoVoList = orderUtils.getOrderInfoVoList(storeOrder);
        List<OrderInfoProductResponse> productList = new ArrayList<>();

        //供应商信息
        Set<Integer> supplierIdList = orderInfoVoList.stream().filter(e -> e.getSuppliersId() != null).map(StoreOrderInfoVo::getSuppliersId).collect(Collectors.toSet());
        Set<Integer> actualSupplierIdList = orderInfoVoList.stream().map(StoreOrderInfoVo::getActualSupplierId).collect(Collectors.toSet());
        supplierIdList.addAll(actualSupplierIdList);
        List<Supplier> supplierList = supplierService.list(Wrappers.lambdaQuery(Supplier.class).in(Supplier::getId, supplierIdList));
        Map<Integer, String> supplierMap = supplierList.stream().collect(Collectors.toMap(Supplier::getId, Supplier::getSuppliersName));
        for (StoreOrderInfoVo infoVo : orderInfoVoList) {
            // 查询是否有手动推送记录
            int purchaseGoodsCount = purchaseGoodsService.count((Wrappers.<PurchaseGoods>lambdaQuery()
                    .eq(PurchaseGoods::getStoreOrderInfoId, infoVo.getId())
                    .eq(PurchaseGoods::getPushType, 1)
            ));

            OrderInfoProductResponse orderInfoProductResponse = new OrderInfoProductResponse();
            if (infoVo.getSuppliersId() != null) {
                orderInfoProductResponse.setSuppliersId(infoVo.getSuppliersId());
                orderInfoProductResponse.setSuppliersName(supplierMap.get(infoVo.getSuppliersId()));
            }
            if (infoVo.getActualSupplierId() != null && infoVo.getActualCost() != null) {
                orderInfoProductResponse.setActualSupplierId(infoVo.getActualSupplierId());
                orderInfoProductResponse.setActualSuppliersName(supplierMap.get(infoVo.getActualSupplierId()));
            }
            StoreProductCartProductInfoResponse productInfo = infoVo.getInfo().getProductInfo();
            StoreProductAttrValue attrInfo = productInfo.getAttrInfo();
            // 自定义skuId
            orderInfoProductResponse.setSelfSourceSkuId(attrInfo.getSelfSourceSkuId());
            orderInfoProductResponse.setStock(infoVo.getStock());
            orderInfoProductResponse.setSkuId(attrInfo.getSourceSkuId());
            orderInfoProductResponse.setAttrId(String.valueOf(attrInfo.getId()));
            orderInfoProductResponse.setBarCode(productInfo.getBarCode());
            discountInfo = infoVo.getInfo().getDiscountInfo();
            orderInfoProductResponse.setSourceCost(attrInfo.getSourceCost());
            orderInfoProductResponse.setOtPrice(attrInfo.getOtPrice());
            orderInfoProductResponse.setOrderInfoId(infoVo.getId());
            orderInfoProductResponse.setProductId(infoVo.getProductId());
            orderInfoProductResponse.setCartNum(infoVo.getNum());
            orderInfoProductResponse.setImage(attrInfo.getImage());
            orderInfoProductResponse.setStoreName(infoVo.getInfo().getProductInfo().getStoreName());
            orderInfoProductResponse.setChildOrderNumber(infoVo.getChildOrderNumber());
            orderInfoProductResponse.setStatus(infoVo.getStatus());
            orderInfoProductResponse.setProductPaidPrice(attrInfo.getProductPaidPrice());
            orderInfoProductResponse.setPaidPrice(attrInfo.getPaidPrice());
            orderInfoProductResponse.setDeductionPrice(attrInfo.getDeductionPrice());
            orderInfoProductResponse.setUseIntegral(attrInfo.getUseIntegral());
            orderInfoProductResponse.setActivityProductPrice(attrInfo.getActivityProductPrice());
//            orderInfoProductResponse.setIsEurope(infoVo.getInfo().getProductInfo().getIsEurope());
            orderInfoProductResponse.setIsEurope(Objects.nonNull(infoVo.getIsEurope()) ? infoVo.getIsEurope() : infoVo.getInfo().getProductInfo().getIsEurope());
            BigDecimal subTotalPrice = null;
            if (storeOrder.getIsChannel() == 1) {
                subTotalPrice = attrInfo.getSubTotalPrice() == null ? attrInfo.getPrice().add(attrInfo.getTaxPrice() == null ? BigDecimal.ZERO : attrInfo.getTaxPrice().add(attrInfo.getSecondPrice() == null ? BigDecimal.ZERO : attrInfo.getSecondPrice())) : attrInfo.getSubTotalPrice();
            }else{
                subTotalPrice = storeOrder.getTotalPrice();
            }
            orderInfoProductResponse.setSubTotalPrice(subTotalPrice);
            //商家改价
            if (attrInfo.getInitialPaidPrice() != null) {
                orderInfoProductResponse.setChangePrice(attrInfo.getPaidPrice().subtract(attrInfo.getInitialPaidPrice()));
            }
            //橙子商品设置keyword为itemCode
            String keyword = infoVo.getInfo().getProductInfo().getKeyword();
            if (ProductTypeEnum.ORANGE.getCode().equals(infoVo.getInfo().getProductInfo().getIsEurope())) {
                StoreProductAttrResult result = storeProductAttrResultService.getByProductId(infoVo.getInfo().getProductId());
                JSONArray jsonArray = JSONArray.parseArray(result.getResult());
                for (Object o : jsonArray) {
                    JSONObject jsonObject = JSONObject.parseObject(o.toString());
                    if (Objects.equals(jsonObject.get("sourceSkuId"), attrInfo.getSourceSkuId())) {
                        keyword = (String) jsonObject.get("skuCode");
                    }
                }
            }
            orderInfoProductResponse.setKeyword(keyword);
            orderInfoProductResponse.setSuk(attrInfo.getSuk());
            orderInfoProductResponse.setTempName(StockAreaTempEnum.getByTempId(infoVo.getInfo().getProductInfo().getTempId()).getStockAreaName());
            orderInfoProductResponse.setPrice(attrInfo.getPrice());
            orderInfoProductResponse.setTotalPrice(attrInfo.getPrice().multiply(new BigDecimal(infoVo.getInfo().getCartNum())));
            OrderInfoDelivery delivery = null;
            if (!BooleanUtils.isTrue(infoVo.getIsVirtual())) {
                delivery = orderInfoDeliveryService.selectDeliveryByOrderInfoId(infoVo.getId());
                orderInfoProductResponse.setDelivery(delivery);
            }
            orderInfoProductResponse.setUserDelivery(orderInfoDeliveryService.getOne(Wrappers.<OrderInfoDelivery>lambdaQuery()
                    .eq(OrderInfoDelivery::getOrderInfoId, infoVo.getId()).eq(OrderInfoDelivery::getChannel, 5).orderByDesc(OrderInfoDelivery::getId).last("LIMIT 1")));
            if (Objects.equals(infoVo.getIsEurope(), ProductTypeEnum.INSIDE.getCode())) {
                orderInfoProductResponse.setProcureStatus(ProcureStatusEnum.NO_PROCURE.getType());
            } else if (Objects.equals(infoVo.getAutonomous(), 1)) {
                orderInfoProductResponse.setProcureStatus(ProcureStatusEnum.AUTO_PROCURE.getType());
            } else {
                if (BooleanUtils.isTrue(infoVo.getIsVirtual())) {
                    orderInfoProductResponse.setProcureStatus(ProcureStatusEnum.FOR_PROCURE.getType());
                } else {
                    List<PurchaseGoods> purchaseGoodsList = purchaseGoodsService.list(Wrappers.lambdaQuery(PurchaseGoods.class).eq(PurchaseGoods::getPushStatus, 1).eq(PurchaseGoods::getPushType, 0).eq(PurchaseGoods::getStoreOrderInfoId, infoVo.getId()));
                    PurchaseGoods one = purchaseGoodsService.getOne(Wrappers.<PurchaseGoods>lambdaQuery().and(qr -> qr.eq(PurchaseGoods::getStatus, OrderStatusEnum.CONFIRM.getCode()).or().eq(PurchaseGoods::getStatus, OrderStatusEnum.CANCEL.getCode())).eq(PurchaseGoods::getStoreOrderInfoId, infoVo.getId()).orderByDesc(PurchaseGoods::getId).last("limit 1"));
                    orderInfoProductResponse.setPurchaseStatus(!Objects.isNull(one));
                    orderInfoProductResponse.setProcureStatus((CollectionUtils.isEmpty(purchaseGoodsList) && delivery == null) ? ProcureStatusEnum.FOR_PROCURE.getType() : ProcureStatusEnum.PROCURE.getType());
                    orderInfoProductResponse.setDeliveryOrderNoList(purchaseGoodsList.stream().map(PurchaseGoods::getChannelOrderSn).collect(Collectors.toList()));
                }
            }
            orderInfoProductResponse.setOrderCode(Integer.toString(Integer.parseInt(infoVo.getOrderId() + "" + infoVo.getId()), 36).toUpperCase());
            orderInfoProductResponse.setDeliveryAddress(infoVo.getDeliveryAddress());
            orderInfoProductResponse.setFirstPrice(attrInfo.getFirstPrice());
            orderInfoProductResponse.setSecondPrice(attrInfo.getSecondPrice());
            orderInfoProductResponse.setTaxPrice(attrInfo.getTaxPrice());
            orderInfoProductResponse.setBrandName(infoVo.getInfo().getProductInfo().getBrandName());
            orderInfoProductResponse.setIsCustoms(0 < count ? true : false);
            orderInfoProductResponse.setIsWzbsc(infoVo.getIsWzbsc());
            orderInfoProductResponse.setIsCainiao(infoVo.getIsCainiao());
            orderInfoProductResponse.setAbnormal(infoVo.getAbnormal());
            orderInfoProductResponse.setActualCost(infoVo.getActualCost());
            orderInfoProductResponse.setIsManualPush(0 < purchaseGoodsCount ? 1 : 0);
            orderInfoProductResponse.setExchangeRate(infoVo.getExchangeRate());
            orderInfoProductResponse.setActualTaxAndFreightCount(infoVo.getActualTaxAndSecondPrice());
            orderInfoProductResponse.setLogisticsType(infoVo.getLogisticsType());
            if (Objects.nonNull(infoVo.getActualStockAreaCode())) {
                StockAreaTempEnum stockAreaTempEnum = StockAreaTempEnum.valueOf(infoVo.getActualStockAreaCode());
                orderInfoProductResponse.setActualStockAreaName(Objects.isNull(stockAreaTempEnum) ? null : stockAreaTempEnum.getStockAreaName());
            }
            orderInfoProductResponse.setActualCostEur(infoVo.getActualCostEur());
            // 物流-运税费
            orderInfoProductResponse.setTaxInternationalPrice(infoVo.getTaxInternationalPrice());
            orderInfoProductResponse.setTaxTurnInlandPrice(infoVo.getTaxTurnInlandPrice());
            orderInfoProductResponse.setTaxInlandDeliveryPrice(infoVo.getTaxInlandDeliveryPrice());
            orderInfoProductResponse.setTaxTaxesPrice(infoVo.getTaxTaxesPrice());
            orderInfoProductResponse.setCouponPrice(infoVo.getCouponPrice());
            //平台供货价
            orderInfoProductResponse.setCost(attrInfo.getCost());
            // 服务商供货价
            if (attrInfo.getFirstAgentId() != null) {
                orderInfoProductResponse.setCost(attrInfo.getFirstAgentCost());
                if (attrInfo.getSecondAgentId() != null) {
                    orderInfoProductResponse.setFirstAgentSupply(attrInfo.getSecondAgentCost());
                    orderInfoProductResponse.setSecondAgentSupply(attrInfo.getCost());
                } else {
                    orderInfoProductResponse.setFirstAgentSupply(attrInfo.getCost());
                }
            }
//            orderInfoProductResponse.setFirstAgentSupply(infoVo.getFirstAgentSupply());
//            orderInfoProductResponse.setSecondAgentSupply(infoVo.getSecondAgentSupply());
//            if (null != infoVo.getFirstAgentCost() && infoVo.getFirstAgentCost().compareTo(BigDecimal.ZERO) > 0) {
//                orderInfoProductResponse.setCost(infoVo.getFirstAgentCost());
//            }
            orderInfoProductResponse.setNote(storeOrderStatusService.getNote(infoVo.getOrderId(), infoVo.getChildOrderNumber(), Constants.ORDER_PLATFORM_NOTE));
            orderInfoProductResponse.setAutonomous(infoVo.getAutonomous());
            orderInfoProductResponse.setVipReducePrice(infoVo.getVipReducePrice());
            orderInfoProductResponse.setActivityId(infoVo.getActivityId());
            if (infoVo.getRefundStatus() != null && infoVo.getStatus() != null) {
                if (infoVo.getRefundStatus() == 1 || infoVo.getStatus() == -1) {
                    StoreOrderRefundApply refundApply = storeOrderRefundApplyService.getOne(Wrappers.<StoreOrderRefundApply>lambdaQuery().eq(StoreOrderRefundApply::getInfoId, infoVo.getId())
                            .orderByDesc(StoreOrderRefundApply::getId).last("LIMIT 1"));
                    orderInfoProductResponse.setStoreOrderRefundApply(refundApply);
                }
            }
            //菜鸟运单号
            orderInfoProductResponse.setCnOrderCode(infoVo.getCnOrderCode());
            orderInfoProductResponse.setRealPlatRatio(infoVo.getRealPlatRatio());
            orderInfoProductResponse.setSuppliersRatio(infoVo.getSuppliersRatio());
            //todo 临时变更 by：包珊珊 永麦->lavita
            if (Objects.equals(orderInfoProductResponse.getSuppliersId(),255)){
                orderInfoProductResponse.setSuppliersName("lavita");
                orderInfoProductResponse.setActualSuppliersName("lavita");
            }

            // 是否推送温州保税仓
            orderInfoProductResponse.setIsWzbsc(infoVo.getIsWzbsc());
            productList.add(orderInfoProductResponse);
        }
        storeOrderInfoResponse.setProductList(productList);
        //统计活动优惠总价
        storeOrderInfoResponse.setActivityTotalDiscount(productList.stream()
                .map(OrderInfoProductResponse::getActivityProductPrice)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        //交易状态
        MerFreezeBill merFreezeBill = merFreezeBillService.getOne(Wrappers.<MerFreezeBill>lambdaQuery().eq(MerFreezeBill::getOrderId, storeOrder.getId()).last("LIMIT 1"));
        if (null != merFreezeBill) {
            int transactionStatus;
            if (Objects.equals(merFreezeBill.getFrozen(), 1)) {
                transactionStatus = 2;
            } else if (Objects.equals(merFreezeBill.getFrozen(), 0) && storeOrder.getStatus().equals(Constants.ORDER_STATUS_H5_REFUNDED)) {
                transactionStatus = 3;
            } else {
                transactionStatus = 1;
            }
            storeOrderInfoResponse.setTransactionStatus(transactionStatus);
        }
        storeOrderInfoResponse.setDiscountInfo(discountInfo);
        return storeOrderInfoResponse;
    }

    /**
     * 发送货物
     *
     * @param request StoreOrderSendRequest 发货参数
     * @return boolean
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Error.class, CrmebException.class})
    public boolean send(StoreOrderSendRequest request) {
        try {

            //订单信息
            StoreOrder storeOrder = getInfoException(request.getId());
            logger.info("request.getType():{}",request.getType());

            switch (request.getType()) {
                case "1":
                    express(request, storeOrder);
                    break;
                case "2":
                    delivery(request, storeOrder);
                    break;
                case "3":
                    virtual(request, storeOrder);
                    break;
                default:
                    throw new CrmebException("类型错误");
            }

            //短信发送

            return true;
        } catch (Exception e) {
            //发货失败！
            throw new CrmebException(e.getMessage());
        }
    }

    /**
     * 备注订单
     *
     * @param id   integer id
     * @param mark String 备注
     * @return boolean
     * @author Mr.Zhang
     * @since 2020-05-28
     */
    @Override
    public boolean mark(Integer id, String mark) {
        StoreOrder storeOrder = getInfoException(id);
        storeOrder.setRemark(mark);
        return updateById(storeOrder);
    }

    /**
     * 拒绝退款
     *
     * @param id     integer id
     * @param reason String 原因
     * @return boolean
     * @author Mr.Zhang
     * @since 2020-05-28
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean refundRefuse(Integer id, String reason) {
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(id);
        if (null == storeOrderInfo) {
            throw new CrmebException("没有找到订单信息");
        }
        if (storeOrderInfo.getRefundStatus() != 1 && storeOrderInfo.getStatus() != -1) {
            throw new CrmebException("该订单不是申请退款状态");
        }
        StoreOrderRefundApply refundApply = storeOrderRefundApplyService.getOne(Wrappers.<StoreOrderRefundApply>lambdaQuery()
                .eq(StoreOrderRefundApply::getInfoId, id)
                .orderByDesc(StoreOrderRefundApply::getId).last("LIMIT 1"));
        if (null == refundApply) {
            throw new CrmebException("订单申请退款记录不存在");
        }
        if (refundApply.getProcessType() != null) {
            throw new CrmebException("该订单已处理");
        }
        refundApply.setProcessType(2);
        refundApply.setProcessTime(new Date());
        refundApply.setRefundRefuseReason(reason);
        storeOrderRefundApplyService.updateById(refundApply);

        storeOrderInfo.setRefundReason(reason);
        storeOrderInfo.setRefundStatus(0);
        storeOrderInfo.setStatus(refundApply.getOldStatus());
        storeOrderInfoService.updateById(storeOrderInfo);
        storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_LOG_REFUND_REFUSE, "拒绝退款");
        //TODO 模板消息通知

        return true;
    }

    /**
     * 查询单条
     *
     * @param storeOrder StoreOrder 订单参数
     * @return StoreOrder
     * @author Mr.Zhang
     * @since 2020-05-28
     */
    @Override
    public StoreOrder getInfoByEntity(StoreOrder storeOrder) {
        LambdaQueryWrapper<StoreOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.setEntity(storeOrder);
        return dao.selectOne(lambdaQueryWrapper);
    }

    /**
     * 根据条件获取
     *
     * @param storeOrder 订单条件
     * @return 结果
     */
    @Override
    public StoreOrder getInfoJustOrderInfo(StoreOrder storeOrder) {
        LambdaQueryWrapper<StoreOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (null != storeOrder.getUnique()) {
            lambdaQueryWrapper.or().eq(StoreOrder::getOrderId, storeOrder.getUnique())
                    .or().eq(StoreOrder::getUnique, storeOrder.getUnique());
        }
        if (null != storeOrder.getUid()) {
            lambdaQueryWrapper.eq(StoreOrder::getUid, storeOrder.getUid());
        }
        if (null != storeOrder.getIsDel()) {
            lambdaQueryWrapper.eq(StoreOrder::getIsDel, storeOrder.getIsDel());
        }
        return dao.selectOne(lambdaQueryWrapper);
    }

    @Override
    public LogisticsResultVo getLogisticsInfo(Integer id) {
        StoreOrder info = getById(id);
        if (StringUtils.isBlank(info.getDeliveryId())) {
            //没有查询到快递信息
            throw new CrmebException("没有查询到快递信息");
        }

        return logisticService.info(info.getDeliveryId(), null);
    }

    @Override
    public String pushWxCustoms(List<Integer> infoIds) {
        try {
            // 查询订单相关信息
            List<StoreOrderInfo> infos = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
                    .in(StoreOrderInfo::getId, infoIds)
            );
            if (CollectionUtils.isEmpty(infos)) {
                return "订单信息丢失!!";
            }
            StoreOrder storeOrder = this.getById(infos.get(0).getOrderId());
            int infoCount = storeOrderInfoService.count(Wrappers.<StoreOrderInfo>lambdaQuery()
                    .in(StoreOrderInfo::getOrderId, infos.get(0).getOrderId())
            );
            String subOrderNo = infos.get(0).getOrderInfoId();
            if (null == storeOrder) {
                return "没有查询到订单信息!";
            }
            if (StringUtil.isEmpty(storeOrder.getOutOrderId())) {
                return "支付单号不存在!";
            }

            int count = storeOrderCustomsService.count(Wrappers.<StoreOrderCustoms>lambdaQuery()
                    .eq(StoreOrderCustoms::getOrderNo, storeOrder.getOrderId())
                    .eq(StoreOrderCustoms::getPayTransactionId, storeOrder.getOutOrderId())
            );
            if (0 < count) {
                return "该笔订单已报关 无需再次申报!";
            }
            // 存在拆单
            boolean isSepara = infoCount > infos.size() ? true : false;
            BigDecimal taxPrice = BigDecimal.ZERO;
            BigDecimal secondPrice = BigDecimal.ZERO;
            BigDecimal paidPrice = BigDecimal.ZERO;
            BigDecimal totalPrice = BigDecimal.ZERO;
            if (isSepara) {
                for (StoreOrderInfo info : infos) {
                    StoreCartResponse cart = JSON.parseObject(info.getInfo(), StoreCartResponse.class);
                    taxPrice = taxPrice.add(cart.getProductInfo().getAttrInfo().getTaxPrice()); // 税费
                    secondPrice = secondPrice.add(cart.getProductInfo().getAttrInfo().getSecondPrice()); // 终端运费
                    paidPrice = paidPrice.add(cart.getProductInfo().getAttrInfo().getProductPaidPrice()); // 商品实际售价
                    totalPrice = totalPrice.add(taxPrice).add(secondPrice).add(paidPrice); // 总价
                }

            }

            // 组装报关清单(暂时支持诚品一家报关宁波关口)
            String appId = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_PAY_ROUTINE_APP_ID + "_" + storeOrder.getMerId());
            String mchId = systemConfigService.getValueByKey(Constants.CONFIG_KEY_PAY_ROUTINE_MCH_ID + "_" + storeOrder.getMerId());
            String signKey = systemConfigService.getValueByKey(Constants.CONFIG_KEY_PAY_ROUTINE_APP_KEY + "_" + storeOrder.getMerId());
//            String customsRecordCode = pushWarehouseFactory.getCustomsRecordCode(infos.get(0).getSuppliersId());
            Result pushResult = PushPayToCustomsUtils.wChatPay(appId, mchId, storeOrder.getOrderId(), storeOrder.getOutOrderId(), "", storeOrder.getIdCard(), StringUtils.defaultIfBlank(storeOrder.getPayName(),storeOrder.getRealName()), signKey);
            if (pushResult == null || !pushResult.isSuccess()){
                return pushResult.getMessage();
            }
            return "支付单申报成功";


//            // 加签信息
//            String sign = generateSign(storeOrder, isSepara, appId, mchId, totalPrice, paidPrice, taxPrice, secondPrice, infos.get(0).getOrderInfoId());
//
//            String xmlRequest = generateXmlRequest(storeOrder, isSepara, appId, mchId, totalPrice, paidPrice, taxPrice, secondPrice, sign, infos.get(0).getOrderInfoId());
//
//            String result = restTemplateUtil.postXml(wechatApiCustomsPushUrl, xmlRequest);
//            Map<String, Object> resultMap = XmlUtil.xmlToMap(result);
//
//            return handleResponse(resultMap, storeOrder, infoIds, result);



            /*StringBuilder sbSignStr = new StringBuilder();
            sbSignStr.append("appid=");
            sbSignStr.append(appId);
            sbSignStr.append("&customs=");
            sbSignStr.append("NINGBO");
            if (isSepara) {
                sbSignStr.append("&fee_type=");
                sbSignStr.append("CNY");
            }
            sbSignStr.append("&mch_customs_no=");
            sbSignStr.append("3303960B04");
            sbSignStr.append("&mch_id=");
            sbSignStr.append(mchId);
            if (isSepara) {
                sbSignStr.append("&order_fee=");
                sbSignStr.append(totalPrice.movePointRight(2).intValue());
            }
            sbSignStr.append("&out_trade_no=");
            sbSignStr.append(storeOrder.getOrderId());
            if (isSepara) {
                sbSignStr.append("&product_fee=");
                sbSignStr.append(paidPrice.movePointRight(2).intValue());
                sbSignStr.append("&sub_order_no=");
                sbSignStr.append(subOrderNo);
            }
            sbSignStr.append("&transaction_id=");
            sbSignStr.append(storeOrder.getOutOrderId());
            if (isSepara) {
                sbSignStr.append("&transport_fee=");
                sbSignStr.append(taxPrice.add(secondPrice).movePointRight(2).intValue());
            }
            sbSignStr.append("&key=");
            sbSignStr.append("wx4a569da0e1e50640wx4a569da0e1ea");
            String sign = DigestUtils.md5Hex(sbSignStr.toString().getBytes("UTF-8")).toUpperCase();
            // 报关信息
            StringBuilder sb = new StringBuilder();
            sb.append("<xml>");
            sb.append("<appid>");
            sb.append(appId);
            sb.append("</appid>");
            sb.append("<customs>");
            sb.append("NINGBO");
            sb.append("</customs>");
            if (isSepara) {
                sb.append("<fee_type>");
                sb.append("CNY");
                sb.append("</fee_type>");
            }
            sb.append("<mch_customs_no>");
            sb.append("3303960B04");
            sb.append("</mch_customs_no>");
            sb.append("<mch_id>");
            sb.append(mchId);
            sb.append("</mch_id>");
            if (isSepara) {
                sb.append("<order_fee>");
                sb.append(totalPrice.movePointRight(2).intValue());
                sb.append("</order_fee>");
            }
            sb.append("<out_trade_no>");
            sb.append(storeOrder.getOrderId());
            sb.append("</out_trade_no>");
            if (isSepara) {
                sb.append("<product_fee>");
                sb.append(paidPrice.movePointRight(2).intValue());
                sb.append("</product_fee>");
                sb.append("<sub_order_no>");
                sb.append(subOrderNo);
                sb.append("</sub_order_no>");
            }
            sb.append("<sign>");
            sb.append(sign);
            sb.append("</sign>");
            sb.append("<transaction_id>");
            sb.append(storeOrder.getOutOrderId());
            sb.append("</transaction_id>");
            if (isSepara) {
                sb.append("<transport_fee>");
                sb.append(taxPrice.add(secondPrice).movePointRight(2).intValue());
                sb.append("</transport_fee>");
            }
            sb.append("</xml>");


            String result = restTemplateUtil.postXml(wechatApiCustomsPushUrl, sb.toString());
            Map<String, Object> resultMap = XmlUtil.xmlToMap(result);
            String msg = resultMap.get("return_msg").toString();
            String code = resultMap.get("result_code").toString();
            if ("SUCCESS".equals(code)) {
                StoreOrderCustoms storeOrderCustoms = new StoreOrderCustoms();
                storeOrderCustoms.setPayVerDept("3");
                storeOrderCustoms.setPayTransactionId(storeOrder.getOutOrderId());
                storeOrderCustoms.setOrderNo(storeOrder.getOrderId());
                storeOrderCustoms.setInfoIds(infoIds.toString());
                storeOrderCustoms.setPayMsg(result);
                storeOrderCustoms.setPayTransactionTime(new Date());
                storeOrderCustoms.setCreateTime(new Date());
                storeOrderCustomsService.save(storeOrderCustoms);
            } else {
                msg = resultMap.get("err_code_des").toString();
            }*/
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private String generateSign(StoreOrder storeOrder, boolean isSepara, String appId, String mchId, BigDecimal totalPrice,
                                BigDecimal paidPrice, BigDecimal taxPrice, BigDecimal secondPrice, String subOrderNo) throws UnsupportedEncodingException {
        StringBuilder sbSignStr = new StringBuilder();
        sbSignStr.append("appid=").append(appId)
                .append("&customs=NINGBO")
                .append(isSepara ? "&fee_type=CNY" : "")
                .append("&mch_customs_no=3303960B04")
                .append("&mch_id=").append(mchId)
                .append(isSepara ? "&order_fee=" + totalPrice.movePointRight(2).intValue() : "")
                .append("&out_trade_no=").append(storeOrder.getOrderId())
                .append(isSepara ? "&product_fee=" + paidPrice.movePointRight(2).intValue() + "&sub_order_no=" + subOrderNo : "")
                .append("&transaction_id=").append(storeOrder.getOutOrderId())
                .append(isSepara ? "&transport_fee=" + taxPrice.add(secondPrice).movePointRight(2).intValue() : "")
                .append("&key=wx4a569da0e1e50640wx4a569da0e1ea");

        return DigestUtils.md5Hex(sbSignStr.toString().getBytes("UTF-8")).toUpperCase();
    }

    private String generateXmlRequest(StoreOrder storeOrder, boolean isSepara, String appId, String mchId, BigDecimal totalPrice,
                                      BigDecimal paidPrice, BigDecimal taxPrice, BigDecimal secondPrice, String sign, String subOrderNo) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>")
                .append("<appid>").append(appId).append("</appid>")
                .append("<customs>NINGBO</customs>")
                .append(isSepara ? "<fee_type>CNY</fee_type>" : "")
                .append("<mch_customs_no>3303960B04</mch_customs_no>")
                .append("<mch_id>").append(mchId).append("</mch_id>")
                .append(isSepara ? "<order_fee>" + totalPrice.movePointRight(2).intValue() + "</order_fee>" : "")
                .append("<out_trade_no>").append(storeOrder.getOrderId()).append("</out_trade_no>")
                .append(isSepara ? "<product_fee>" + paidPrice.movePointRight(2).intValue() + "</product_fee><sub_order_no>" + subOrderNo + "</sub_order_no>" : "")
                .append("<sign>").append(sign).append("</sign>")
                .append("<transaction_id>").append(storeOrder.getOutOrderId()).append("</transaction_id>")
                .append(isSepara ? "<transport_fee>" + taxPrice.add(secondPrice).movePointRight(2).intValue() + "</transport_fee>" : "")
                .append("</xml>");

        return sb.toString();
    }

    private String handleResponse(Map<String, Object> resultMap, StoreOrder storeOrder, List<Integer> infoIds, String result) {
        String msg = resultMap.get("return_msg").toString();
        String code = resultMap.get("result_code").toString();

        if ("SUCCESS".equals(code)) {
            StoreOrderCustoms storeOrderCustoms = new StoreOrderCustoms();
            storeOrderCustoms.setPayVerDept("3");
            storeOrderCustoms.setPayTransactionId(storeOrder.getOutOrderId());
            storeOrderCustoms.setOrderNo(storeOrder.getOrderId());
            storeOrderCustoms.setInfoIds(infoIds.toString());
            storeOrderCustoms.setPayMsg(result);
            storeOrderCustoms.setPayTransactionTime(new Date());
            storeOrderCustoms.setCreateTime(new Date());
            storeOrderCustomsService.save(storeOrderCustoms);
        } else {
            msg = resultMap.get("err_code_des").toString();
        }

        return msg;
    }

    /**
     * 汇付支付单报关
     */
    @Override
    public String pushAdapayCustoms(List<Integer> infoIds) {
        try {
            // 查询订单相关信息
            List<StoreOrderInfo> infos = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
                    .in(StoreOrderInfo::getId, infoIds)
            );
            if (CollectionUtils.isEmpty(infos)) {
                return "订单信息丢失!!";
            }
            int orderId = infos.get(0).getOrderId();
            StoreOrder storeOrder = this.getById(orderId);
            int infoCount = storeOrderInfoService.count(Wrappers.<StoreOrderInfo>lambdaQuery()
                    .in(StoreOrderInfo::getOrderId, infos.get(0).getOrderId())
            );
            if (null == storeOrder) {
                return "没有查询到订单信息!";
            }
            if (StringUtil.isEmpty(storeOrder.getOutOrderId())) {
                return "该笔订单不允许报关!";
            }
            int count = storeOrderCustomsService.count(Wrappers.<StoreOrderCustoms>lambdaQuery()
                    .eq(StoreOrderCustoms::getOrderNo, storeOrder.getOrderId())
                    .eq(StoreOrderCustoms::getPayTransactionId, storeOrder.getOutOrderId())
            );
            if (0 < count) {
                return "该笔订单已报关 无需再次申报!";
            }
            // 存在拆单
//			boolean isSepara = infoCount > infos.size() ? true : false;
            BigDecimal firstPrice = BigDecimal.ZERO;
            BigDecimal taxPrice = BigDecimal.ZERO;
            BigDecimal secondPrice = BigDecimal.ZERO;
            BigDecimal paidPrice = BigDecimal.ZERO;
            BigDecimal totalPrice = BigDecimal.ZERO;
//			if(isSepara) {
            for (StoreOrderInfo info : infos) {
                // 退款金额不申报
                if (info.getRefundStatus() == 2 || info.getRefundStatus() == 3) {
                    continue;
                }
                StoreCartResponse cart = JSON.parseObject(info.getInfo(), StoreCartResponse.class);
                firstPrice = firstPrice.add(cart.getProductInfo().getAttrInfo().getFirstPrice()); // 头层
                secondPrice = secondPrice.add(cart.getProductInfo().getAttrInfo().getSecondPrice()); // 终端运费
                taxPrice = taxPrice.add(cart.getProductInfo().getAttrInfo().getTaxPrice()); // 税费
                paidPrice = paidPrice.add(cart.getProductInfo().getAttrInfo().getProductPaidPrice()); // 商品实际售价
                totalPrice = totalPrice.add(firstPrice).add(secondPrice).add(taxPrice).add(paidPrice); // 总价
            }
            // 订单总金额查询订单支付金额
            totalPrice = storeOrder.getPayPrice();


//			}
            // 报关
            // TODO DIDIOK 支付23
            HttpSendResult result = adapayDegreePayOrderProcess.payCustoms(storeOrder.getMerId(), storeOrder.getRealName(), storeOrder.getIdCard(),
                    storeOrder.getOrderId(), storeOrder.getOutOrderId(), totalPrice, firstPrice.add(secondPrice), paidPrice, taxPrice, BigDecimal.ZERO);
            String respTxt = result.getResponseBody();
            if (result.getStatus() == 200) {
                String errorCode = AdapayDegreePayOrderProcess.getRespParam(respTxt, "errorCode");
                String respMsg = AdapayDegreePayOrderProcess.getRespParam(respTxt, "errorMsg");
                if (!"000000".equals(errorCode)) {
                    log.error("--------------- 汇付聚合支付报关其他失败!: {}", respMsg);
                    throw new CrmebException(respMsg);
                } else {
                    StoreOrderCustoms storeOrderCustoms = new StoreOrderCustoms();
                    storeOrderCustoms.setPayVerDept("3");
                    storeOrderCustoms.setPayTransactionId(storeOrder.getOutOrderId());
                    storeOrderCustoms.setOrderNo(storeOrder.getOrderId());
                    storeOrderCustoms.setInfoIds(infoIds.toString());
                    storeOrderCustoms.setPayMsg(respTxt);
                    storeOrderCustoms.setPayTransactionTime(new Date());
                    storeOrderCustoms.setCreateTime(new Date());
                    storeOrderCustomsService.save(storeOrderCustoms);
                }
            } else {
                log.error("--------------- 汇付聚合支付报关失败!: {}", respTxt);
                throw new CrmebException("报关请求失败!");
            }

            return "成功";
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 连连支付单报关
     */
    @Override
    public String pushLianlianCustoms(List<Integer> infoIds) {
        try {
            // 查询订单相关信息
            List<StoreOrderInfo> infos = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
                    .in(StoreOrderInfo::getId, infoIds)
            );
            if (CollectionUtils.isEmpty(infos)) {
                return "订单信息丢失!!";
            }
            int orderId = infos.get(0).getOrderId();
            StoreOrder storeOrder = this.getById(orderId);
            int infoCount = storeOrderInfoService.count(Wrappers.<StoreOrderInfo>lambdaQuery()
                    .in(StoreOrderInfo::getOrderId, infos.get(0).getOrderId())
            );
            if (null == storeOrder) {
                return "没有查询到订单信息!";
            }
            // todo outOrderId
            log.error("第三方订单号outOrderId:{}", storeOrder.getOutOrderId());
            if (StringUtil.isEmpty(storeOrder.getOutOrderId())) {
                return "该笔订单不允许报关!";
            }
            int count = storeOrderCustomsService.count(Wrappers.<StoreOrderCustoms>lambdaQuery()
                    .eq(StoreOrderCustoms::getOrderNo, storeOrder.getOrderId())
                    .eq(StoreOrderCustoms::getPayPushStatus, Boolean.TRUE)
            );
            if (0 < count) {
                return "该笔订单已报关 无需再次申报!";
            }

            // 存在拆单
            BigDecimal firstPrice = BigDecimal.ZERO;
            BigDecimal taxPrice = BigDecimal.ZERO;
            BigDecimal secondPrice = BigDecimal.ZERO;
            BigDecimal paidPrice = BigDecimal.ZERO;
            BigDecimal totalPrice = BigDecimal.ZERO;
            for (StoreOrderInfo info : infos) {
                // 退款金额不申报
                if (info.getRefundStatus() == 2 || info.getRefundStatus() == 3) {
                    continue;
                }
                StoreCartResponse cart = JSON.parseObject(info.getInfo(), StoreCartResponse.class);
                firstPrice = firstPrice.add(cart.getProductInfo().getAttrInfo().getFirstPrice()); // 头层
                secondPrice = secondPrice.add(cart.getProductInfo().getAttrInfo().getSecondPrice()); // 终端运费
                taxPrice = taxPrice.add(cart.getProductInfo().getAttrInfo().getTaxPrice()); // 税费
                paidPrice = paidPrice.add(cart.getProductInfo().getAttrInfo().getProductPaidPrice()); // 商品实际售价
//                totalPrice = totalPrice.add(firstPrice).add(secondPrice).add(taxPrice).add(paidPrice); // 总价
            }
            // 订单总金额查询订单支付金额
            totalPrice = storeOrder.getPayPrice();
            // 报关
            CustomsPushPayResponse result = lianlianDegreePayOrderProcess.payCustoms(storeOrder.getMerId(), storeOrder.getRealName(), storeOrder.getIdCard(),
                    storeOrder.getOrderId(), storeOrder.getOrderId(), totalPrice, firstPrice.add(secondPrice), paidPrice, taxPrice, BigDecimal.ZERO, storeOrder.getPayTime(), false);

            String ret_code = result.getRet_code();
            String ret_msg = result.getRet_msg();
            String oid_partner = result.getOid_partner();
            String txn_seqno = result.getTxn_seqno();
            String accp_txno = result.getAccp_txno();
            String org_txn_seqno = result.getOrg_txn_seqno();
            String push_status = result.getPush_status();
            String pay_company_code = result.getPay_company_code();
            String pay_company_name = result.getPay_company_name();
            String pay_transaction_id = result.getPay_transaction_id();
            String push_date = result.getPush_date();
            String push_failReason = result.getPush_failReason();
            String result_info = result.getResult_info();

            // 返回结果
            if ("0000".equals(ret_code)) {
                if ("PUSH_SUCCESSED".equals(push_status)) {
                    StoreOrderCustoms storeOrderCustoms = new StoreOrderCustoms();
                    storeOrderCustoms.setPayVerDept("3");
                    storeOrderCustoms.setPayTransactionId(pay_transaction_id);
                    // 子订单号
                    storeOrderCustoms.setOrderNo(storeOrder.getOrderId());
//                        storeOrderCustoms.setInfoIds(infoIds.toString());
                    storeOrderCustoms.setPayMsg(ret_msg);
                    storeOrderCustoms.setPayPushMsg(push_status);
                    storeOrderCustoms.setPayPushStatus(Boolean.TRUE);
                    storeOrderCustoms.setPayTransactionTime(new Date());
                    storeOrderCustoms.setCreateTime(new Date());
                    storeOrderCustomsService.save(storeOrderCustoms);
                } else if ("PUSH_APPLY".equals(push_status)) {
                    log.info("--------------- 连连聚合支付报关:推送申请（连连受理请求，暂未推送到海关的瞬时状态）!");
                } else if ("PROCESSING".equals(push_status)) {
                    log.info("--------------- 连连聚合支付报关:处理中");
                } else {
                    log.error("--------------- 连连聚合支付报关其他失败!: {}", push_failReason);
                    throw new CrmebException(push_failReason);
                }
            } else {
                log.error("--------------- 连连聚合支付报关失败!: {}", ret_msg);
                throw new CrmebException("报关请求失败!");
            }
            return "成功";
        }catch (Exception e) {
            log.error("--------------- 连连聚合支付报关异常!:", e);
            throw new CrmebException("连连聚合支付报关异常!");
        }
    }

    /**
     * 根据用户id获取订单数据
     *
     * @param userId 用户id
     * @return
     */
    @Override
    public RetailShopOrderDataResponse getOrderDataByUserId(Integer userId) {
        QueryWrapper<StoreOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(pay_price) as totalPrice, count(id) as id");
        queryWrapper.ge("paid", 1);
        queryWrapper.ge("refund_status", 0);
        queryWrapper.eq("uid", userId);
        queryWrapper.groupBy("uid");
        StoreOrder storeOrder = dao.selectOne(queryWrapper);
        RetailShopOrderDataResponse rop = new RetailShopOrderDataResponse();
        if (null != storeOrder) {
            rop.setOrderCount(storeOrder.getId()); // id=借变量传递数据
            rop.setOrderPrice(storeOrder.getTotalPrice());
        }

        return rop;
    }

    /**
     * 根据用户id集合获取对应订单，分销中使用
     *
     * @param ids 用户id集合
     * @return 对应用户订单集合
     */
    @Override
    public List<StoreOrder> getOrderByUserIdsForRetailShop(List<Integer> ids) {
        LambdaQueryWrapper<StoreOrder> lqw = new LambdaQueryWrapper<>();
        lqw.in(StoreOrder::getUid, ids);
        lqw.ge(StoreOrder::getPaid, 1);
        lqw.ge(StoreOrder::getRefundStatus, 0);
        return dao.selectList(lqw);
    }

    /**
     * 订单 top 查询参数
     *
     * @param status 状态参数
     * @return 订单查询结果
     */
    @Override
    public List<StoreOrder> getTopDataUtil(int status, int userId) {
        LambdaQueryWrapper<StoreOrder> lqw = new LambdaQueryWrapper<>();
        statusApiByWhere(lqw, status);
        lqw.eq(StoreOrder::getIsDel, false);
        lqw.eq(StoreOrder::getUid, userId);
        return dao.selectList(lqw);
    }

    @Override
    public List<String> queryOrderIds(Date startTime) {
        QueryWrapper<StoreOrder> wapper = new QueryWrapper<>();
        wapper.select("order_id");
        wapper.eq("paid", 1);
        wapper.eq("refund_status", 0);
        wapper.eq("is_del", 0);
        wapper.gt("pay_time", startTime);
        wapper.eq("push_status", 0);
        List<Object> list = dao.selectObjs(wapper);
        return list == null ? Lists.newArrayList() : list.stream().map(o -> o.toString()).collect(Collectors.toList());
    }

    @Override
    public void push(TmallStoreOrderRequest order, List<TmallOrderInfoRequest> orderInfoRequestList) {
        StoreOrder storeOrder = new StoreOrder();
        BeanUtils.copyProperties(order, storeOrder);
        storeOrder.setPayType("tmall");
        storeOrder.setUid(293);
        storeOrder.setIsChannel(1);
        //订单来源 1 寻物 2天猫
        storeOrder.setSource(2);
        storeOrder.setMark("");
        storeOrder.setPaid(true);
        storeOrder.setStatus(Constants.ORDER_STATUS_H5_NOT_SHIPPED);
        storeOrder.setUnique(DigestUtils.md5Hex(order.getOrderId()));
        storeOrder.setAreaType(AreaTypeEnum.HK.getType());
        dao.insert(storeOrder);

        List<StoreOrderInfo> storeOrderInfos = new ArrayList<>();
        for (TmallOrderInfoRequest tmallOrderInfo : orderInfoRequestList) {
            StoreOrderInfo soInfo = new StoreOrderInfo();
            StoreProduct storeProduct = storeProductService.getById(tmallOrderInfo.getProductId());
            if (null != storeProduct) {
                tmallOrderInfo.getProductInfo().setImage(storeProduct.getImage());
                tmallOrderInfo.getProductInfo().setKeyword(storeProduct.getKeyword());
                soInfo.setIsEurope(storeProduct.getIsEurope());
            }
            String sourceSkuId = tmallOrderInfo.getProductInfo().getAttrInfo().getSourceSkuId();
            StoreProductAttrValue storeProductAttrValue = storeProductAttrValueService.getOne(Wrappers.<StoreProductAttrValue>lambdaQuery()
                    .eq(StoreProductAttrValue::getSourceSkuId, sourceSkuId)
                    .last("LIMIT 1")
            );
            if (null != storeProductAttrValue) {
                tmallOrderInfo.getProductInfo().setTempId(storeProductAttrValue.getTempId());
            }
            soInfo.setOrderId(storeOrder.getId());
            soInfo.setProductId(tmallOrderInfo.getProductId());
            soInfo.setInfo(JSON.toJSON(tmallOrderInfo).toString());
            soInfo.setUnique(DigestUtils.md5Hex(tmallOrderInfo.toString()));
            storeOrderInfos.add(soInfo);
            //减库存
            log.info("天猫推送下单减商品product库存,原来库存stock:{},需要减去库存cartNum:{}", storeProduct.getStock(), tmallOrderInfo.getCartNum());
            storeProduct.setStock(storeProduct.getStock() - tmallOrderInfo.getCartNum());
            storeProductService.updateById(storeProduct);
            //减attvalue库存
            subtractStock(storeProduct, tmallOrderInfo);
        }
        // 保存购物车商品详情
        boolean saveBatchOrderInfosResult = storeOrderInfoService.saveOrderInfos(storeOrderInfos);
        if (!saveBatchOrderInfosResult) {
            throw new CrmebException("订单生成失败");
        }

        //天猫订单记录增加
        String message = "同步天猫订单";
        storeOrderStatusService.createLog(storeOrder.getId(), Constants.ORDER_LOG_TMALL_ORDER, message);

//        Object validateCode = redisUtil.get(SmsConstants.SMS_VALIDATE_PHONE+("15601955175"));
//        if(null == validateCode){
//            SendSmsVo sendSmsVo = new SendSmsVo();
//            sendSmsVo.setMobiles("15601955175");
//            sendSmsVo.setSendEnable(sendenable);
//            sendSmsVo.setTemplate(SmsConstants.SMS_ORDER_TEMPLATEID);
//            smsService.sendMessage(sendSmsVo);
//        }
    }

    @Transactional
    @Override
    public Boolean pushOutOrder(OutOrderRequest outOrderRequest, ChannelMerchant channelMerchant) {
        // 创建寻物订单对象
        StoreOrder storeOrder = new StoreOrder();
        storeOrder.setOrderId("OT" + outOrderRequest.getOrderId());
        storeOrder.setRealName(outOrderRequest.getRealName());
        storeOrder.setUserPhone(outOrderRequest.getUserPhone());
        storeOrder.setUserAddress(outOrderRequest.getUserAddress());
        storeOrder.setFreightPrice(outOrderRequest.getFreightPrice());
        storeOrder.setTotalNum(outOrderRequest.getTotalNum());
        storeOrder.setTotalPrice(outOrderRequest.getTotalPrice());
        storeOrder.setPayPrice(outOrderRequest.getPayPrice());
        storeOrder.setPayTime(outOrderRequest.getPayTime());
        storeOrder.setCreateTime(outOrderRequest.getCreateTime());
        storeOrder.setCreateName(outOrderRequest.getCreateName());
        storeOrder.setProvince(outOrderRequest.getProvince());
        storeOrder.setCity(outOrderRequest.getCity());
        storeOrder.setDistrict(outOrderRequest.getDistrict());
        storeOrder.setDetail(outOrderRequest.getDetail());
        storeOrder.setMerId(channelMerchant.getId());
        storeOrder.setIdCard(outOrderRequest.getIdCard());
        // 第三方支付订单
        storeOrder.setPayType("other");
        // 默认绑定一个寻物用户
        storeOrder.setUid(293);
        storeOrder.setIsChannel(1);
        // 订单来源 1 寻物 2第三方
        storeOrder.setSource(2);
        // 支付成功
        storeOrder.setPaid(true);
        storeOrder.setStatus(Constants.ORDER_STATUS_H5_CONFIRM);
        storeOrder.setUnique(DigestUtils.md5Hex(outOrderRequest.getOrderId()));
        storeOrder.setAreaType(outOrderRequest.getAreaType());
        storeOrder.setMark(null == outOrderRequest.getMark() ? "" : outOrderRequest.getMark());
        storeOrder.setExpressUrl(outOrderRequest.getExpressUrl());
        storeOrder.setOutOrderSource(outOrderRequest.getOutOrderSource());
        dao.insert(storeOrder);

        // 创建订单详情
        List<StoreOrderInfo> storeOrderInfos = new ArrayList<>();
        List<OutOrderInfoRequest> outOrderInfoRequests = outOrderRequest.getOutOrderInfoRequest();
        BigDecimal payPrice = BigDecimal.ZERO;

        StoreProduct storeProduct = null;
        StoreProductAttrValue storeProductAttrValue =null;
        boolean flag = true;
        for (OutOrderInfoRequest outOrderInfo : outOrderInfoRequests) {

            if(outOrderRequest.getOutOrderSource()==OutOrderSourceEnum.JKY.getCode()){

                storeProductAttrValue = storeProductAttrValueService.getOne(Wrappers.<StoreProductAttrValue>lambdaQuery()
                        .eq(StoreProductAttrValue::getSelfSourceSkuId, outOrderInfo.getBarCode())
                        .last("LIMIT 1"));

                if (null == storeProductAttrValue) {
                    throw new CrmebException("该sku不存在!");
                }

                // 校验商品
                storeProduct = storeProductService.getById(storeProductAttrValue.getProductId());

            }else
            {

                // 校验商品
                storeProduct = storeProductService.getOne(Wrappers.<StoreProduct>lambdaQuery()
                        .eq(StoreProduct::getBarCode, outOrderInfo.getBarCode())
                        .last("LIMIT 1")
                );

                storeProductAttrValue = storeProductAttrValueService.getOne(Wrappers.<StoreProductAttrValue>lambdaQuery()
                        .eq(StoreProductAttrValue::getBarCode, outOrderInfo.getBarCode())
                        .eq(StoreProductAttrValue::getSourceSkuId, outOrderInfo.getSourceSkuId())
                        .last("LIMIT 1")
                );

            }

            if (null == storeProduct) {
                throw new CrmebException("该商品不存在!");
            }

            if (null == storeProductAttrValue) {
                throw new CrmebException("该sku不存在!");
            }
            if (outOrderInfo.getCartNum() > storeProductAttrValue.getStock()) {
                throw new CrmebException("该sku库存不足!");
            }
            if (BooleanUtils.isNotTrue(outOrderRequest.getIsTof()) && flag && !Objects.equals(storeProduct.getTempId(), 1) && Objects.equals(outOrderRequest.getAreaType(), 1)) {
                //验证订单商品发货地（非大陆地区发货且大陆收货的情况下需要填写身份证）
                if (StringUtils.isBlank(outOrderRequest.getIdCard())) {
                    throw new CrmebException("非大陆地区发货且大陆收货的情况下需要填写身份证!");
                }
                //校验身份证
                idCardUtils.checkIdCard(outOrderRequest.getRealName(), outOrderRequest.getIdCard());
                flag = false;
            }
            // 计算商户成本价和平台成本价
            BigDecimal sourceCost = storeProductAttrValue.getPrice().setScale(2, BigDecimal.ROUND_DOWN);
            BigDecimal cost = storeProductAttrValue.getPrice().setScale(2, BigDecimal.ROUND_DOWN);
            MarkupRateRequest rateRequest = new MarkupRateRequest();
            rateRequest.setMerId(channelMerchant.getId());
            rateRequest.setType(MarkupRateTypeEnum.PLAT_平台加价率.getType());
            BigDecimal platRatio = markupRateService.selectMerchantRatio(rateRequest);
            cost = cost.add(cost.multiply(platRatio.divide(new BigDecimal("100"))).setScale(2, BigDecimal.ROUND_DOWN));

            BigDecimal firstPrice = BigDecimal.ZERO;
            BigDecimal secondPrice =BigDecimal.ZERO;
            BigDecimal taxPrice =BigDecimal.ZERO;

            if(outOrderRequest.getOutOrderSource()==OutOrderSourceEnum.JKY.getCode()){
                //税费
                taxPrice =outOrderRequest.getTaxAmount();
                payPrice =outOrderRequest.getTotalPrice();
                cost = outOrderInfo.getPrice();
                secondPrice =outOrderRequest.getFreightPrice();

            }else
            {

                //是否包邮
                boolean freeShipping = priceUtil.freeShipping(storeProduct.getSuppliersId(), channelMerchant.getId());
                CategoryMatch categoryMatch = categoryMatchService.getById(storeProduct.getCateId());
                //首段物流
                firstPrice = priceUtil.getFirstPriceNew(storeProduct.getIsEurope(), storeProduct.getTempId(), AreaTypeEnum.CN.getType(), channelMerchant, freeShipping, categoryMatch, storeProduct.getSuppliersId());
                //供货价  2023.3.23去掉 下面统一加
//            cost = cost.add(firstPrice);
                //终端物流
                BigDecimal weight = priceUtil.getProductWeightByStoreCar(storeProductAttrValue.getProductId(),storeProductAttrValue.getSourceSkuId());
                Supplier productSupplier = supplierService.getById(storeProduct.getSuppliersId());
                secondPrice = priceUtil.getSecondPriceNew(storeProduct, AreaTypeEnum.CN.getType(), channelMerchant, freeShipping, productSupplier.getId(),
                        weight, productSupplier.getDirectMailType(),cost,storeProductAttrValue.getSourceSkuId(),null);
                //税费
                taxPrice = priceUtil.getTaxPriceNew(storeProduct, AreaTypeEnum.CN.getType(),
                        cost.add(firstPrice).add(secondPrice), channelMerchant, cost, freeShipping, false,true);
                BigDecimal price = (cost.add(firstPrice).add(secondPrice).add(taxPrice)).multiply(new BigDecimal(outOrderInfo.getCartNum()));
                payPrice = payPrice.add(price);
            }

            for (int i = 0; i < outOrderInfo.getCartNum(); i++) {
                StoreCartResponse response = new StoreCartResponse();
//                OutOrderInfoRequest OrderInfo = new OutOrderInfoRequest();
                response.setCartNum(1);
                response.setCostPrice(cost);
                response.setProductId(storeProduct.getId());
                response.setTruePrice(cost);
                StoreProductCartProductInfoResponse productInfo = new StoreProductCartProductInfoResponse();
                // 订单商品切片填充
//                Product product = new Product();
                productInfo.setId(storeProduct.getId());
                productInfo.setOtPrice(storeProduct.getOtPrice());
                productInfo.setPrice(cost);
                productInfo.setStoreName(storeProduct.getStoreName());
                productInfo.setBarCode(storeProduct.getBarCode());
                productInfo.setTempId(storeProductAttrValue.getTempId());
                productInfo.setKeyword(storeProduct.getKeyword());
                productInfo.setImage(storeProduct.getImage());
                productInfo.setIsEurope(storeProduct.getIsEurope());
                productInfo.setPlatRatio(platRatio);
                productInfo.setCateId(storeProduct.getCateId());
                productInfo.setBrandName(storeProduct.getBrandName());
                StoreProductAttrValue attrInfo = new StoreProductAttrValue();
                // attr属性
//                AttrInfo attrInfo = new AttrInfo();
                attrInfo.setFirstPrice(firstPrice);

                attrInfo.setSuk(storeProductAttrValue.getSuk());
                attrInfo.setBarCode(storeProductAttrValue.getBarCode());
                attrInfo.setPrice(cost);
                attrInfo.setSourceSkuId(storeProductAttrValue.getSourceSkuId());
                attrInfo.setCost(cost);
                attrInfo.setSourceCost(sourceCost);
                attrInfo.setOtPrice(storeProductAttrValue.getOtPrice());
                attrInfo.setProductPaidPrice(cost);

                attrInfo.setDeductionPrice(BigDecimal.ZERO);
                attrInfo.setUseIntegral(BigDecimal.ZERO);
                attrInfo.setAttrValue(storeProductAttrValue.getAttrValue());
                attrInfo.setImage(storeProductAttrValue.getImage());
                attrInfo.setProductId(storeProduct.getId());
                attrInfo.setSelfSourceSkuId(storeProductAttrValue.getSelfSourceSkuId());

                if(outOrderRequest.getOutOrderSource()==OutOrderSourceEnum.JKY.getCode()){

                    attrInfo.setSecondPrice(secondPrice.divide(BigDecimal.valueOf(outOrderInfo.getCartNum())).setScale(2, RoundingMode.HALF_UP));
                    attrInfo.setTaxAndSecondPrice(taxPrice.add(secondPrice).add(firstPrice).divide(BigDecimal.valueOf(outOrderInfo.getCartNum())).setScale(2, RoundingMode.HALF_UP));
                    attrInfo.setTaxPrice(taxPrice.divide(BigDecimal.valueOf(outOrderInfo.getCartNum())).setScale(2, RoundingMode.HALF_UP));
                    attrInfo.setPaidPrice(cost.add(attrInfo.getTaxAndSecondPrice()));
                    
                }else
                {
                    attrInfo.setTaxAndSecondPrice(taxPrice.add(secondPrice).add(firstPrice));
                    attrInfo.setTaxPrice(taxPrice);
                    attrInfo.setPaidPrice(cost.add(attrInfo.getTaxAndSecondPrice()));
                    attrInfo.setSecondPrice(secondPrice);

                }
                attrInfo.setSubTotalPrice(attrInfo.getPaidPrice());
                productInfo.setAttrInfo(attrInfo);
                response.setProductInfo(productInfo);
                StoreOrderInfo storeOrderInfo = new StoreOrderInfo();
                storeOrderInfo.setOrderId(storeOrder.getId());
                storeOrderInfo.setProductId(storeProduct.getId());
                storeOrderInfo.setInfo(JSON.toJSON(response).toString());
//                storeOrderInfo.setUnique(DigestUtils.md5Hex(OrderInfo.toString()));
                storeOrderInfo.setUnique(storeProductAttrValue.getSourceSkuId());
                storeOrderInfo.setSuppliersId(storeProduct.getSuppliersId());
                storeOrderInfo.setStatus(Constants.ORDER_STATUS_H5_CONFIRM);
                storeOrderInfo.setRefundStatus(0);

                if(outOrderRequest.getOutOrderSource()==OutOrderSourceEnum.JKY.getCode()){

                    storeOrderInfo.setPayPrice(outOrderRequest.getPayPrice().divide(BigDecimal.valueOf(outOrderInfo.getCartNum())).setScale(2, RoundingMode.HALF_UP));
                    storeOrderInfo.setTaxPrice(outOrderRequest.getTaxAmount().divide(BigDecimal.valueOf(outOrderInfo.getCartNum())).setScale(2, RoundingMode.HALF_UP));
                }else
                {
                    storeOrderInfo.setPayPrice(attrInfo.getPaidPrice());
                }

                storeOrderInfo.setOrderInfoId(CrmebUtil.getOrderNo(Constants.PAY_TYPE_TMALL_PAY));
                storeOrderInfo.setExchangeRate(storeProduct.getExchangeRate());

                Integer isEurope;
                if (Objects.equals(storeProduct.getIsEurope(), ProductTypeEnum.INSIDE.getCode())) {
                    isEurope = storeProduct.getConvertIsEurope() == null ? ProductTypeEnum.INSIDE.getCode() : storeProduct.getConvertIsEurope();
                    Supplier supplier = supplierService.getOne(Wrappers.<Supplier>lambdaQuery().eq(Supplier::getMerId, channelMerchant.getId()));
                    if (supplier != null && Objects.equals(supplier.getId(), storeProduct.getSuppliersId())) {
                        isEurope = ProductTypeEnum.INSIDE.getCode();
                    }
                } else {
                    isEurope = storeProduct.getIsEurope();
                }
                storeOrderInfo.setIsEurope(isEurope);
                if (isEurope != 1 && Objects.equals(channelMerchant.getAutoPush(), 1)) {
                    storeOrderInfo.setAutonomous(0);
                }
                //推送地址
                storeOrderInfo.setDeliveryAddress(storeProduct.getTempId() != 1 && !ProductTypeEnum.ORANGE.getCode().equals(storeProduct.getIsEurope())
                        && !ProductTypeEnum.INSIDE.getCode().equals(storeProduct.getIsEurope()) ? channelMerchant.getDetail() : outOrderRequest.getDetail());
                storeOrderInfos.add(storeOrderInfo);
            }
            // 减库存
            log.info("--------------- 商品id: {},sourceSkuId:{}, 扣除库存: {}, 外部订单号: {} ---------------", storeProduct.getId(), storeProductAttrValue.getSourceSkuId(), outOrderInfo.getCartNum(), outOrderRequest.getOrderId());
            storeProductService.subProductStock(storeProduct.getId(), outOrderInfo.getCartNum());
            // 减AttValue库存
            if(outOrderRequest.getOutOrderSource()==OutOrderSourceEnum.JKY.getCode()){
                storeProductAttrValueService.subProductStockByJky( storeProductAttrValue.getSelfSourceSkuId(), outOrderInfo.getCartNum());

            }else
            {
                storeProductAttrValueService.subProductStock(storeProduct.getId(), storeProductAttrValue.getSourceSkuId(), outOrderInfo.getCartNum());
            }

        }
        //校验余额
        ChannelMerchantAccount account = channelMerchantAccountService.getOne(Wrappers.<ChannelMerchantAccount>lambdaQuery().eq(ChannelMerchantAccount::getMerId, channelMerchant.getId()).last("LIMIT 1"));
        if (account.getAccount().compareTo(payPrice) < 0) {
            throw new CrmebException("账户可用余额不足!");
        }
        // 更新订单实际支付金额
        this.update(Wrappers.<StoreOrder>lambdaUpdate()
                .eq(StoreOrder::getId, storeOrder.getId())
                .set(StoreOrder::getPayPrice, payPrice)
        );
        //扣除商户可用余额
        ChannelMerchantAccount merchantAccount = new ChannelMerchantAccount();
        merchantAccount.setMerId(channelMerchant.getId()).setAccount(payPrice.negate());
        channelMerchantAccountService.calcMoney(merchantAccount);
        log.info("外部订单推送,扣除商户可用余额;商户:{},金额:{}", channelMerchant.getId(), payPrice);
        //记录流水
        accountFlowService.saveAccountFlow(storeOrder.getMerId(), storeOrder.getId(), null, null,
                AccountFlowTypeEnum.PRODUCT, payPrice.negate(), null, null, "第三方购买商品");
        // 保存订单详情
        boolean saveBatchOrderInfosResult = storeOrderInfoService.saveOrderInfos(storeOrderInfos);
        List<StoreOrderInfo> orderInfoList = storeOrderInfoService.list(Wrappers.lambdaQuery(StoreOrderInfo.class).eq(StoreOrderInfo::getOrderId, storeOrder.getId()));
        orderInfoList.forEach(e -> e.setChildOrderNumber(Long.toString(Long.parseLong(storeOrder.getId() + "" + e.getId()), 36).toUpperCase()));
        storeOrderInfoService.saveOrUpdateBatch(orderInfoList);
        if (!saveBatchOrderInfosResult) {
            throw new CrmebException("订单生成失败");
        }
        // 订单log记录增加
        String message = "同步外部订单";
        storeOrderStatusService.createLog(storeOrder.getId(), storeOrder.getOrderId(), Constants.ORDER_LOG_OTHER_ORDER, message);
        return true;
    }

    @Override
    public List<StoreOrderExcelVo> getExportList(StoreOrderSearchRequest request, PageParamRequest pageParamRequest,SystemAdmin systemAdmin) {
        getStoreOrderListRequest(request,systemAdmin);
//        request.setRequestSource("ADMIN");
        PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
//        List<StoreOrderProduct> storeOrderList = dao.getExportList(request);
        List<StoreOrderInfo> childOrderList = dao.selectChildOrderListByUnionQuery(request);
        if (CollectionUtils.isEmpty(childOrderList)){
            return Collections.emptyList();
        }

        final List<StoreOrderExcelVo> storeOrderExcelVos = Collections.synchronizedList(new ArrayList<>());

        List<List<StoreOrderInfo>> partition = ListUtils.partition(childOrderList, 10);
        CompletableFuture[] array = partition.stream().map(k -> CompletableFuture.runAsync(() -> {
            List<StoreOrderExcelVo> result = formatStoreOrderExcelVoNew(k);
            if (CollectionUtils.isNotEmpty(result)) {
                storeOrderExcelVos.addAll(result);
            }
        })).toArray(CompletableFuture[]::new);

        try {
            CompletableFuture.allOf(array).get(10, TimeUnit.MINUTES);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return storeOrderExcelVos;
    }

    private List<StoreOrderExcelVo> formatStoreOrderExcelVoNew(List<StoreOrderInfo> childOrderList) {
        List<StoreOrderExcelVo> storeOrderExcelVoList = new ArrayList<>();
        if (CollectionUtils.isEmpty(childOrderList)) {
            return storeOrderExcelVoList;
        }
        //主订单集合
        List<Integer> orderIdList = childOrderList.stream().map(StoreOrderInfo::getOrderId).distinct().collect(Collectors.toList());
        List<StoreOrder> storeOrderList = dao.selectList(Wrappers.lambdaQuery(StoreOrder.class).in(StoreOrder::getId, orderIdList));
        Map<Integer, StoreOrder> storeOrderMap = storeOrderList.stream().collect(Collectors.toMap(StoreOrder::getId, e -> e));
        //下单用户列表
        Set<Integer> userIdList = storeOrderList.stream().map(StoreOrder::getUid).collect(Collectors.toSet());
        List<User> userList = userService.list(Wrappers.lambdaQuery(User.class).in(User::getUid, userIdList));
        //推广人列表
        Map<Integer, User> spreadMap = new HashMap<>();
        userList.forEach(e -> {
            if (spreadMap.get(e.getUid()) == null) {
                User spread = Optional.ofNullable(userService.getById(e.getSpreadUid())).orElse(new User());
                spreadMap.put(e.getUid(), spread);
            }
        });
        //商户信息
        List<ChannelMerchant> channelMerchants = channelMerchantService.list();
        Map<Integer, ChannelMerchant> channelMerchantMap = channelMerchants.stream().collect(Collectors.toMap(ChannelMerchant::getId, s -> s, (value1, value2) -> value1));
        //供应商信息
        Set<Integer> supplierIdList = childOrderList.stream().filter(e -> e.getSuppliersId() != null).map(StoreOrderInfo::getSuppliersId).collect(Collectors.toSet());
        Set<Integer> actualSupplierIdList = childOrderList.stream().map(StoreOrderInfo::getActualSupplierId).collect(Collectors.toSet());
        supplierIdList.addAll(actualSupplierIdList);
        List<Supplier> supplierList = supplierService.list(Wrappers.lambdaQuery(Supplier.class).in(Supplier::getId, supplierIdList));
        Map<Integer, String> supplierMap = supplierList.stream().collect(Collectors.toMap(Supplier::getId, Supplier::getSuppliersName));
        // 购物车数据map
        Map<String, StoreCartResponse> cartResponseMap = new HashMap<>();
        Set<Integer> productIdSet = new HashSet<>();
        for (StoreOrderInfo storeOrderInfo : childOrderList) {
            StoreCartResponse storeCartResponse = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);
            if (Objects.isNull(storeCartResponse)){
                continue;
            }
            productIdSet.add(storeCartResponse.getProductId());
            cartResponseMap.put(storeCartResponse.getProductAttrUnique(),storeCartResponse);
        }
        List<StoreProduct> storeProducts = storeProductService.listByIds(productIdSet);
        Map<Integer, StoreProduct> storeProductMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(storeProducts)){
            storeProductMap = storeProducts.stream().collect(Collectors.toMap(StoreProduct::getId, v->v));
        }
        for (StoreOrderInfo storeOrderInfo : childOrderList) {
            StoreOrderExcelVo storeOrderExcelVo = new StoreOrderExcelVo();
            StoreOrder storeOrder = storeOrderMap.get(storeOrderInfo.getOrderId());
            storeOrderExcelVo.setCreateTime(DateFormatUtils.format(storeOrder.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
            storeOrderExcelVo.setOrderNumber(storeOrder.getOrderId());
            //商户名
            if (null != storeOrder.getMerId()) {
                ChannelMerchant channelMerchant = channelMerchantMap.get(storeOrder.getMerId());
                if (null != channelMerchant) {
                    storeOrderExcelVo.setMerName(channelMerchant.getChannelName());
                }
            }
            //主订单
            storeOrderExcelVo.setOrderType(storeOrder.getShippingType() == 1 ? "快递订单" : "自提订单");
            storeOrderExcelVo.setCreateName(storeOrder.getCreateName());
            storeOrderExcelVo.setSpreadName(spreadMap.get(storeOrder.getUid()) != null ? spreadMap.get(storeOrder.getUid()).getNickname() : "");
            User leader = userService.getById(storeOrder.getLeaderId());
            storeOrderExcelVo.setLeaderName(leader != null ? leader.getNickname() : "--");
            storeOrderExcelVo.setPayTypeStr(getPayType(storeOrder.getPayType()));
            if (storeOrder.getUseIntegral() > 0) {
                storeOrderExcelVo.setPayTypeStr(storeOrderExcelVo.getPayTypeStr() + " / 积分抵扣");
            }
            storeOrderExcelVo.setTotalPriceCNY(storeOrder.getPayPrice().add(storeOrder.getDeductionPrice()).add(storeOrder.getCouponPrice()).add(storeOrder.getVipReducePrice()));
            storeOrderExcelVo.setGoodsPriceCNY(storeOrder.getTotalPrice());
            storeOrderExcelVo.setFreightAndTaxPrice(storeOrder.getPayPostage());
            storeOrderExcelVo.setPayPrice(storeOrder.getPayPrice());
            storeOrderExcelVo.setDeductedPrice(storeOrder.getDeductionPrice());
            storeOrderExcelVo.setCouponPrice(storeOrder.getCouponPrice());
            storeOrderExcelVo.setChildOrderNumber(storeOrderInfo.getChildOrderNumber());
            storeOrderExcelVo.setOrderStatus(getStatusStr(storeOrderInfo.getStatus()));
            storeOrderExcelVo.setRefundStatus(getRefundStatusStr(storeOrderInfo.getRefundStatus()));
            //退款信息
            if (storeOrderInfo.getRefundStatus() == 2 || storeOrderInfo.getRefundStatus() == 3) {
                List<StoreAccountInfo> accountInfoList = storeAccountInfoService.list(Wrappers.lambdaQuery(StoreAccountInfo.class).eq(StoreAccountInfo::getUid, storeOrder.getUid())
                        .eq(StoreAccountInfo::getOrderId, storeOrderInfo.getChildOrderNumber()).eq(StoreAccountInfo::getTradeType, OrderTradeTypeEnum.REFUND.getType()).orderByAsc(StoreAccountInfo::getCreateTime));
                storeOrderExcelVo.setRefundPrice(accountInfoList.stream().map(StoreAccountInfo::getTradePrice).map(BigDecimal::toString).collect(Collectors.joining(" / ")));
                storeOrderExcelVo.setRefundTime(accountInfoList.stream().map(StoreAccountInfo::getCreateTime).map(e -> DateFormatUtils.format(e, "yyyy-MM-dd HH:mm:ss")).collect(Collectors.joining(" / ")));
                Set<Integer> adminIdList = accountInfoList.stream().map(StoreAccountInfo::getOperateId).collect(Collectors.toSet());
                if (CollectionUtils.isNotEmpty(adminIdList)) {
                    List<SystemAdmin> systemAdminList = systemAdminService.list(Wrappers.lambdaQuery(SystemAdmin.class).in(SystemAdmin::getId, adminIdList));
                    Map<Integer, String> systemAdminMap = systemAdminList.stream().collect(Collectors.toMap(SystemAdmin::getId, SystemAdmin::getRealName));
                    storeOrderExcelVo.setRefundOperator(accountInfoList.stream().map(StoreAccountInfo::getOperateId).map(systemAdminMap::get).collect(Collectors.joining(" / ")));
                }
            }
            StoreCartResponse storeCartResponse = null;
            if (MapUtils.isNotEmpty(cartResponseMap)&&cartResponseMap.containsKey(storeOrderInfo.getUnique())){
                storeCartResponse = cartResponseMap.get(storeOrderInfo.getUnique());
            }else {
                storeCartResponse = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);
            }
            StoreProductCartProductInfoResponse productInfo = storeCartResponse.getProductInfo();
            StoreProductAttrValue attrInfo = productInfo.getAttrInfo();
            //商品信息
            storeOrderExcelVo.setProductId(storeCartResponse.getProductId());
            storeOrderExcelVo.setProductName(productInfo.getStoreName());
            storeOrderExcelVo.setBrandName(productInfo.getBrandName());
            storeOrderExcelVo.setCloudProduct("否");
            if (MapUtils.isNotEmpty(storeProductMap) && storeProductMap.containsKey(storeCartResponse.getProductId())){
                StoreProduct storeProduct = storeProductMap.get(storeCartResponse.getProductId());
                storeOrderExcelVo.setCloudProduct(null != storeProduct.getIsEurope() && storeProduct.getIsEurope()==1?"否":"是");
            }

            // 图片压缩
            String imgUrl = attrInfo.getImage();
            imgUrl = StringUtil.isEmpty(imgUrl) ? "" : imgUrl.substring(0, !imgUrl.contains("?") ? imgUrl.length() : imgUrl.indexOf("?")) + "?x-oss-process=image/resize,m_fill,w_100,h_100";
            storeOrderExcelVo.setImage(imgUrl);
            storeOrderExcelVo.setKeyword(productInfo.getKeyword());
            storeOrderExcelVo.setSpecification(attrInfo.getAttrValue());
            storeOrderExcelVo.setQuantity(storeCartResponse.getCartNum());
            //子订单价格信息
            storeOrderExcelVo.setOtPriceEUR(attrInfo.getOtPrice() == null ? productInfo.getOtPrice() : attrInfo.getOtPrice());
            storeOrderExcelVo.setSourceCostCNY(attrInfo.getSourceCost());
            //平台供货价
            storeOrderExcelVo.setCostCNY(attrInfo.getCost());
            // 服务商供货价
            if (attrInfo.getFirstAgentId() != null) {
                storeOrderExcelVo.setCostCNY(attrInfo.getFirstAgentCost());
            }
            //价格转换处理
            storeOrderExcelVo.setOtPriceCNY(priceUtil.eur2RmbStatic(storeOrderExcelVo.getOtPriceEUR(), storeOrderInfo.getExchangeRate()));
            storeOrderExcelVo.setSourceCostEUR(attrInfo.getSourceCost() == null ? null : priceUtil.rmb2EurStatic(attrInfo.getSourceCost(), storeOrderInfo.getExchangeRate()));
            storeOrderExcelVo.setCostEUR(attrInfo.getCost() == null ? null : priceUtil.rmb2EurStatic(storeOrderExcelVo.getCostCNY(), storeOrderInfo.getExchangeRate()));
            storeOrderExcelVo.setActualCostCNY(storeOrderInfo.getActualCost());
            storeOrderExcelVo.setPrice(attrInfo.getPrice());
            storeOrderExcelVo.setFirstPrice(attrInfo.getFirstPrice());
            storeOrderExcelVo.setSecondPrice(attrInfo.getSecondPrice());
            storeOrderExcelVo.setTaxPrice(attrInfo.getTaxPrice());
            storeOrderExcelVo.setProductPaidPrice(attrInfo.getProductPaidPrice());
            storeOrderExcelVo.setSubDeductionPrice(storeOrderInfo.getDeductionPrice());
            storeOrderExcelVo.setSubCouponPrice(storeOrderInfo.getCouponPrice());
            storeOrderExcelVo.setPaidPrice(storeOrderInfo.getPayPrice());
            if (storeOrderInfo.getActualSupplierId() != null && storeOrderInfo.getActualCost() != null) {
                storeOrderExcelVo.setActualSupplierName(supplierMap.get(storeOrderInfo.getActualSupplierId()));
                storeOrderExcelVo.setActualCostEur(storeOrderInfo.getActualCostEur());
            }
            if (Objects.nonNull(storeOrderInfo.getActualStockAreaCode())) {
                storeOrderExcelVo.setActualStockAreaName(StockAreaTempEnum.valueOf(storeOrderInfo.getActualStockAreaCode()).getStockAreaName());
            }
            if (storeOrderInfo.getSuppliersId() != null) {
                storeOrderExcelVo.setSupplierName(supplierMap.get(storeOrderInfo.getSuppliersId()));
            }
            //发货信息
            storeOrderExcelVo.setTempName(StockAreaTempEnum.getByTempId(productInfo.getTempId()).getStockAreaName());
            List<OrderInfoDelivery> orderInfoDeliveryList = orderInfoDeliveryService.list(Wrappers.lambdaQuery(OrderInfoDelivery.class).eq(OrderInfoDelivery::getOrderInfoId, storeOrderInfo.getId()).orderByAsc(OrderInfoDelivery::getId));
            if (CollectionUtils.isNotEmpty(orderInfoDeliveryList)) {
                storeOrderExcelVo.setDeliveryTime(orderInfoDeliveryList.stream().map(OrderInfoDelivery::getCreateTime).map(e -> DateFormatUtils.format(e, "yyyy-MM-dd HH:mm:ss")).collect(Collectors.joining(" / ")));
                storeOrderExcelVo.setDeliveryCompany(orderInfoDeliveryList.stream().map(OrderInfoDelivery::getDeliveryCompany).collect(Collectors.joining(" / ")));
                storeOrderExcelVo.setDeliveryNumber(orderInfoDeliveryList.stream().map(OrderInfoDelivery::getDeliveryNumber).collect(Collectors.joining(" / ")));
            }
            //收货人信息
            storeOrderExcelVo.setRealName(storeOrder.getRealName());
            storeOrderExcelVo.setUserPhone(storeOrder.getUserPhone());
            storeOrderExcelVo.setDetail(storeOrder.getUserAddress());
            storeOrderExcelVo.setIdCard(storeOrder.getIdCard());
            //商品采购信息
            if (Objects.equals(storeOrderInfo.getIsEurope(), ProductTypeEnum.INSIDE.getCode())) {
                storeOrderExcelVo.setProcureStatus(ProcureStatusEnum.NO_PROCURE.getTypeName());
            } else if (Objects.equals(storeOrderInfo.getAutonomous(), 1)) {
                storeOrderExcelVo.setProcureStatus(ProcureStatusEnum.AUTO_PROCURE.getTypeName());
            } else {
                if (BooleanUtils.isTrue(storeOrderInfo.getIsVirtual())) {
                    storeOrderExcelVo.setProcureStatus(ProcureStatusEnum.FOR_PROCURE.getTypeName());
                } else {
                    PurchaseGoods automaticPurchaseGoods = purchaseGoodsService.getOne(Wrappers.lambdaQuery(PurchaseGoods.class).eq(PurchaseGoods::getPushType, 0).eq(PurchaseGoods::getStoreOrderInfoId, storeOrderInfo.getId()).eq(PurchaseGoods::getPushStatus, 1)
                            .orderByDesc(PurchaseGoods::getCreateTime).last("LIMIT 1"));
                    storeOrderExcelVo.setProcureStatus((automaticPurchaseGoods == null && CollectionUtils.isEmpty(orderInfoDeliveryList)) ? ProcureStatusEnum.FOR_PROCURE.getTypeName() : ProcureStatusEnum.PROCURE.getTypeName());
                    if (automaticPurchaseGoods != null) {
                        storeOrderExcelVo.setDeliveryOrderNo(automaticPurchaseGoods.getChannelOrderSn());
                    }
                    PurchaseGoods purchaseGoods = Optional.ofNullable(purchaseGoodsService.getOne(Wrappers.lambdaQuery(PurchaseGoods.class).eq(PurchaseGoods::getStoreOrderInfoId, storeOrderInfo.getId()).eq(PurchaseGoods::getPushType, 1).eq(PurchaseGoods::getPushStatus, 1)
                            .orderByDesc(PurchaseGoods::getCreateTime).last("LIMIT 1"))).orElse(new PurchaseGoods());
                    storeOrderExcelVo.setManualDeliveryOrderNo(purchaseGoods.getChannelOrderSn());
                }
            }
            storeOrderExcelVo.setExchangeRate(storeOrderInfo.getExchangeRate());
            storeOrderExcelVo.setNote(storeOrderStatusService.getNote(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_PLATFORM_NOTE));
            storeOrderExcelVo.setMark(storeOrder.getMark());
            storeOrderExcelVo.setRefundReason(storeOrderInfo.getRefundReasonWapExplain());
            storeOrderExcelVoList.add(storeOrderExcelVo);
        }
        return storeOrderExcelVoList;
    }


    private String getRefundStatusStr(Integer refundStatus) {
        if (null == refundStatus) {
            return "";
        }
        if (Integer.valueOf(0).equals(refundStatus)) {
            return "未退款";
        } else if (Integer.valueOf(1).equals(refundStatus)) {
            return "申请中";
        } else if (Integer.valueOf(2).equals(refundStatus)) {
            return "已退款";
        } else if (Integer.valueOf(3).equals(refundStatus)) {
            return "补偿性退款";
        }
        return "";
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////// 以下为自定义方法

    /**
     * 退款扣除积分/余额
     *
     * @param request StoreOrderRefundRequest 退款参数
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    private void subtractBill(StoreOrderRefundRequest request, String category, String type, String foundsType) {
        try {
            FundsMonitorSearchRequest fundsMonitorSearchRequest = new FundsMonitorSearchRequest();
            fundsMonitorSearchRequest.setCategory(category);
            fundsMonitorSearchRequest.setType(type);
            fundsMonitorSearchRequest.setLinkId(request.getOrderId().toString());
            fundsMonitorSearchRequest.setPm(1);

            PageParamRequest pageParamRequest = new PageParamRequest();
            pageParamRequest.setLimit(Constants.EXPORT_MAX_LIMIT);
            List<UserBill> list = userBillService.getList(fundsMonitorSearchRequest, pageParamRequest);

            if (null == list || list.size() < 1) {
                return;
            }

            for (UserBill userBill : list) {
                User user = userService.getById(userBill.getUid());
                if (null == user) {
                    continue;
                }
                BigDecimal price;
                if (category.equals(Constants.USER_BILL_CATEGORY_INTEGRAL)) {
                    price = user.getIntegral();
                } else {
                    price = user.getBrokeragePrice();
                }

                if (userBill.getNumber().compareTo(price) > 0) {
                    userBill.setNumber(price);
                    //更新佣金
                    UserOperateFundsRequest userOperateFundsRequest = new UserOperateFundsRequest();
                    userOperateFundsRequest.setUid(user.getUid());
                    userOperateFundsRequest.setValue(request.getAmount());
                    userOperateFundsRequest.setFoundsType(foundsType);
                    userOperateFundsRequest.setType(0);
                    userService.updateFounds(userOperateFundsRequest, false); //更新佣金/积分
                    if (category.equals(Constants.USER_BILL_CATEGORY_INTEGRAL)) {
                        userBillService.saveRefundIntegralBill(request, user);
                    } else {
                        userBillService.saveRefundBrokeragePriceBill(request, user);
                    }
                }
            }
        } catch (Exception e) {
            throw new CrmebException("更新退款佣金/积分失败");
        }
    }

    /**
     * 发货
     *
     * @param id Integer id
     * @return Boolean
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    public StoreOrder getInfoException(Integer id) {
        StoreOrder info = getById(id);
        if (null == info) {
            throw new CrmebException("没有找到订单信息");
        }
        return info;
    }


    /**
     * 快递
     *
     * @param request    StoreOrderSendRequest 发货参数
     * @param storeOrder StoreOrder 订单信息
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    private void express(StoreOrderSendRequest request, StoreOrder storeOrder) {
        logger.info("express入口:{}；{}",JSON.toJSONString(request),JSON.toJSONString(storeOrder));
        try {
            if (!storeOrder.getStatus().equals(Constants.ORDER_STATUS_H5_SPIKE) && !storeOrder.getStatus().equals(Constants.ORDER_STATUS_H5_NOT_SHIPPED)) {
                throw new CrmebException("当前订单状态无法发货");
            }
            if (request.getChannel() == null) {
                throw new CrmebException("操作方式不能为空!");
            }
            if (request.getChannel() == 1 || (request.getChannel() == 0 && request.getLogisticsType() != 0) || (request.getChannel() == 2 && request.getLogisticsType() == 0)) {
                throw new CrmebException("操作方式参数异常!");
            }
            //快递信息
            Express express = expressService.info(Integer.parseInt(request.getExpressId()));
            StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(request.getOrderInfoId());
            // 设置订单状态为待收货
            if (Constants.ORDER_STATUS_H5_NOT_SHIPPED == storeOrderInfo.getStatus() || request.getIsConfirm()) {
                storeOrderInfo.setStatus(Constants.ORDER_STATUS_H5_SPIKE);
                if (!storeOrder.getStatus().equals(Constants.ORDER_STATUS_H5_SPIKE)) {
                    storeOrder.setStatus(Constants.ORDER_STATUS_H5_SPIKE);
                    this.updateById(storeOrder);
                }
            }
            if (request.getChannel() == 2) {
                if (storeOrderInfo.getLogisticsType() == 0) {
                    throw new CrmebException("该订单物流部门无操作权限!");
                }
                if (storeOrderInfo.getLogisticsType() != 1 && !storeOrderInfo.getLogisticsType().equals(request.getLogisticsType())) {
                    throw new CrmebException("订单物流方式不一致,请重新选择");
                }
                storeOrderInfo.setLogisticsType(request.getLogisticsType());
            }
            storeOrderInfoService.updateById(storeOrderInfo);
            StoreCartResponse response = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);
            //物流信息列表
            List<OrderInfoDelivery> deliveryList = orderInfoDeliveryService.list(Wrappers.<OrderInfoDelivery>lambdaQuery().eq(OrderInfoDelivery::getOrderInfoId, request.getOrderInfoId()).eq(OrderInfoDelivery::getIsExchange, 0));
            //发货
            if (deliveryList.size() < 1) {
                //改变推送订单状态
                Supplier supplier = supplierService.getById(storeOrderInfo.getActualSupplierId());
                if (supplier != null) {
                    purchaseGoodsService.update(Wrappers.<PurchaseGoods>lambdaUpdate().set(PurchaseGoods::getStatus, Constants.ORDER_STATUS_H5_SPIKE)
                            .eq(PurchaseGoods::getStoreOrderInfoId, storeOrderInfo.getId()).eq(PurchaseGoods::getStatus, Constants.ORDER_STATUS_H5_NOT_SHIPPED)
                            .eq(PurchaseGoods::getGoodsSupplier, supplier.getSuppliersName()));
                }
            }
            String message = (deliveryList.size() < 1 ? Constants.ORDER_LOG_MESSAGE_EXPRESS : Constants.ORDER_LOG_ADD_MESSAGE_EXPRESS)
                    .replace("{storeName}", response.getProductInfo().getStoreName()).replace("{suk}", response.getProductInfo().getAttrInfo().getSuk())
                    .replace("{channel}", request.getChannel() == 0 ? "平台" : "物流部门").replace("{deliveryName}", express.getName()).replace("{deliveryCode}", request.getExpressCode());
            storeOrderStatusService.createLog(request.getId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_LOG_EXPRESS, message);
            //新增物流信息
            OrderInfoDeliveryRequest delivery = new OrderInfoDeliveryRequest();
            delivery.setOrderInfoId(request.getOrderInfoId());
            delivery.setDeliveryCompany(express.getName());
            delivery.setDeliveryNumber(request.getExpressCode());
            delivery.setName(request.getName());
            delivery.setDeliveryCode(express.getCode());
            delivery.setPhone(request.getPhone());
            delivery.setExpressId(Integer.parseInt(request.getExpressId()));
            delivery.setLogisticsStage(request.getLogisticsStage());
            if (!Objects.isNull(request.getLevel())) {
                delivery.setLevel(request.getLevel());
            }
            delivery.setChannel(request.getChannel());
            orderInfoDeliveryService.addDelivery(delivery);
            logger.info("orderInfoDeliveryService.addDeliver下面:{}",JSON.toJSONString(delivery));

            // 发货消息推送
            List<StoreOrderInfo> storeOrderInfos = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
                    .eq(StoreOrderInfo::getOrderId, storeOrder.getId())
            );
            List<Integer> infoIds = storeOrderInfos.stream().map(StoreOrderInfo::getId).collect(Collectors.toList());
            List<OrderInfoDelivery> orderInfoDeliverys = orderInfoDeliveryService.list(Wrappers.<OrderInfoDelivery>lambdaQuery()
                    .in(OrderInfoDelivery::getOrderInfoId, infoIds)
                    .last("GROUP BY order_info_id")
            );
            if (infoIds.size() == orderInfoDeliverys.size()) {
                List<OrderInfoDelivery> orderInfoDeliverys2 = orderInfoDeliveryService.list(Wrappers.<OrderInfoDelivery>lambdaQuery()
                        .in(OrderInfoDelivery::getOrderInfoId, infoIds)
                );
                OutStoreOrderResponse outStoreOrderResponse = new OutStoreOrderResponse();
                outStoreOrderResponse.setOrderId(storeOrder.getOrderId());
                outStoreOrderResponse.setOrderInfoDeliverys(orderInfoDeliverys2);

               //吉客云回传
               if(1 == storeOrder.getOutOrderSource()) {
                   JkyDeliverGoods(storeOrder,storeOrderInfo);
               }

                if (27 == storeOrder.getMerId()) {
                    if(ExpressTransition.getValueByCode(express.getCode()) == null){
                        throw new CrmebException("海带云不支持该快递！");
                    }
                    deliverGoods(storeOrder.getOrderId().split("OT")[1], ExpressTransition.getValueByCode(express.getCode()).getValue(), request.getExpressCode());
                } else {
                    sendBackOrder(storeOrder.getMerId(), outStoreOrderResponse, storeOrder.getBackCount());
                }
            }

            //todo 发货异步后置处理器（目前乱写的，待优化哈）
            afterDeliveryAsyncHandler(storeOrderInfo,storeOrder);

        } catch (Exception e) {
            throw new CrmebException("快递发货失败！" + e.getMessage());
        }

    }

    private void afterDeliveryAsyncHandler(StoreOrderInfo storeOrderInfo, StoreOrder storeOrder) {
        logger.info("afterDeliveryAsyncHandler:{}；{}",JSON.toJSONString(storeOrderInfo),JSON.toJSONString(storeOrder));
        OrderConfirmContext orderConfirmContext = new OrderConfirmContext();
        orderConfirmContext.setStoreOrderInfo(storeOrderInfo);
        orderConfirmContext.setStoreOrder(storeOrder);
        //todo  暂时固定别样平台的处理器
        CompletableFuture.runAsync(()->{
            boolean execute = orderConfirmInterface.execute(orderConfirmContext);
        });

    }

    /**
     * 订单发货通知
     *
     * @param @param merId
     * @param @param OrderInfoDeliverys
     * @return void
     * @throws
     * @Description:
     * @author daigb
     */
    private void sendBackOrder(Integer merId, OutStoreOrderResponse outStoreOrderResponse, Integer backCount) {
        ChannelMerchant channelMerchant = channelMerchantService.getById(merId);
        if (null == channelMerchant || StringUtils.isEmpty(channelMerchant.getBackUrl())) {
            log.info("--------------- 推送订单发货通知, 该商户不存在或者未配置回调url: {} ---------------", channelMerchant);
            return;
        }
        // 加密签名
        Long millis = System.currentTimeMillis();
        String token = ProductUtil.getSign(millis.toString(), channelMerchant.getMerchantNo(), channelMerchant.getMerchantSecret());
        outStoreOrderResponse.setMillis(millis);
        outStoreOrderResponse.setToken(token);

        backCount = null == backCount ? 1 : backCount + 1;
        Boolean backStatus = false;
        try {
            String result = restTemplateUtil.postStringData(channelMerchant.getBackUrl(), JSON.toJSONString(outStoreOrderResponse));
            log.info("--------------- 推送订单发货通知, 商户号: {}, 订单号: {}, 物流列表: {}, 回调地址: {}, 返回信息: {} ---------------", channelMerchant.getMerchantNo(), outStoreOrderResponse.getOrderId(), JSON.toJSONString(outStoreOrderResponse.getOrderInfoDeliverys()), channelMerchant.getBackUrl(), result);

            if (StringUtil.isNotEmpty(result)) {
                String backCode = JSONObject.parseObject(result).get("code").toString();
                if ("200".equals(backCode)) {
                    backStatus = true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        this.update(Wrappers.<StoreOrder>lambdaUpdate()
                .eq(StoreOrder::getOrderId, outStoreOrderResponse.getOrderId())
                .set(StoreOrder::getBackCount, backCount)
                .set(StoreOrder::getBackStatus, backStatus)
        );

    }

    /**
     * 送货上门
     *
     * @param request    StoreOrderSendRequest 发货参数
     * @param storeOrder StoreOrder 订单信息
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    private void delivery(StoreOrderSendRequest request, StoreOrder storeOrder) {
        ValidateFormUtil.isPhone(request.getExpressCode(), "收货人联系方式");

        try {
            //送货信息
            storeOrder.setDeliveryName(request.getExpressId());
            storeOrder.setDeliveryId(request.getExpressCode());
            storeOrder.setStatus(Constants.ORDER_STATUS_H5_SPIKE);
            storeOrder.setDeliveryType("send");
            updateById(storeOrder);

            //获取购买商品名称
            List<Integer> orderIdList = new ArrayList<>();
            orderIdList.add(storeOrder.getId());

            HashMap<Integer, List<StoreOrderInfoVo>> orderInfoMap = storeOrderInfoService.getMapInId(orderIdList);
            if (orderInfoMap.isEmpty() || !orderInfoMap.containsKey(storeOrder.getId())) {
                throw new CrmebException("没有找到购买的商品信息");
            }
            List<String> productNameList = new ArrayList<>();
            for (StoreOrderInfoVo storeOrderInfoVo : orderInfoMap.get(storeOrder.getId())) {
//                productNameList.add(storeOrderInfoVo.getInfo().getJSONObject("productInfo").getString("store_name"));
                productNameList.add(storeOrderInfoVo.getInfo().getProductInfo().getStoreName());
            }


            //订单记录增加
            String message = Constants.ORDER_LOG_MESSAGE_DELIVERY.replace("{deliveryName}", request.getExpressId()).replace("{deliveryCode}", request.getExpressCode());
            storeOrderStatusService.createLog(request.getId(), Constants.ORDER_LOG_DELIVERY, message);

            //微信模板消息发送
            HashMap<String, String> map = new HashMap<>();
            map.put(Constants.WE_CHAT_TEMP_KEY_FIRST, "订单发货提醒");
            map.put("keyword1", StringUtils.join(productNameList, "|"));
            map.put("keyword2", DateUtil.dateToStr(storeOrder.getCreateTime(), Constants.DATE_FORMAT));
            map.put("keyword3", storeOrder.getUserAddress());
            map.put("keyword4", request.getExpressId());
            map.put("keyword5", request.getExpressCode());
            map.put(Constants.WE_CHAT_TEMP_KEY_END, "欢迎再次购买！");

            templateMessageService.push(Constants.WE_CHAT_TEMP_KEY_DELIVERY, map, storeOrder.getUid(), Constants.PAY_TYPE_WE_CHAT_FROM_PUBLIC);

        } catch (Exception e) {
            throw new CrmebException("送货上门发货失败！");
        }
    }

    /**
     * 虚拟
     *
     * @param request    StoreOrderSendRequest 发货参数
     * @param storeOrder StoreOrder 订单信息
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    private void virtual(StoreOrderSendRequest request, StoreOrder storeOrder) {
        try {
            //快递信息
            storeOrder.setDeliveryType("fictitious");
            storeOrder.setStatus(Constants.ORDER_STATUS_H5_SPIKE);
            updateById(storeOrder);

            //订单记录增加
            storeOrderStatusService.createLog(request.getId(), Constants.ORDER_LOG_DELIVERY_VI, Constants.ORDER_LOG_DELIVERY_VI);

            //微信模板消息发送
        } catch (Exception e) {
            e.printStackTrace();
            throw new CrmebException("虚拟物品发货失败");
        }


    }

    /**
     * 获取总数
     *
     * @param request 请求参数
     * @return Integer
     * @author Mr.Zhang
     * @since 2020-06-12
     */
    private List<StoreOrderInfo> getCount(StoreOrderSearchRequest request,SystemAdmin systemAdmin) {
        StoreOrderSearchRequest searchRequest = new StoreOrderSearchRequest();
        BeanUtils.copyProperties(request, searchRequest);
        searchRequest.setStatus(null);
        getStoreOrderListRequest(searchRequest,systemAdmin);
        return dao.selectChildCountByCondition(searchRequest);
    }

    /**
     * 获取request的where条件
     *
     * @param queryWrapper QueryWrapper<StoreOrder> 表达式
     * @param request      StoreOrderSearchRequest 请求参数
     * @author Mr.Zhang
     * @since 2020-06-12
     */
    private void getRequestWhere(QueryWrapper<StoreOrder> queryWrapper, StoreOrderSearchRequest request) {
        getRequestOrderIdWhere(queryWrapper, request);
        getRequestUidWhere(queryWrapper, request);
        getRequestTimeWhere(queryWrapper, request);
    }

    private void getIsDelWhere(QueryWrapper<StoreOrder> queryWrapper, Boolean isDel) {
        if (null != isDel) {
            queryWrapper.eq("is_del", isDel);
        }
    }

    /**
     * 查询条件 - 后台删除标识
     *
     * @param queryWrapper
     * @param isSystemDel
     */
    private void getIsSystemDelWhere(QueryWrapper<StoreOrder> queryWrapper, Boolean isSystemDel) {
        if (null != isSystemDel) {
            queryWrapper.eq("is_system_del", isSystemDel);
        }
    }

    /**
     * 获取request的where条件
     *
     * @param queryWrapper QueryWrapper<StoreOrder> 表达式
     * @param request      StoreOrderSearchRequest 请求参数
     * @author Mr.Zhang
     * @since 2020-06-12
     */
    private void getRequestOrderIdWhere(QueryWrapper<StoreOrder> queryWrapper, StoreOrderSearchRequest request) {
        if (StringUtils.isNotBlank(request.getOrderId())) {
            queryWrapper.eq("order_id", request.getOrderId());
        }
    }

    /**
     * 获取request的where条件
     *
     * @param queryWrapper QueryWrapper<StoreOrder> 表达式
     * @param request      StoreOrderSearchRequest 请求参数
     * @author Mr.Zhang
     * @since 2020-06-12
     */
    private void getRequestUidWhere(QueryWrapper<StoreOrder> queryWrapper, StoreOrderSearchRequest request) {
        if (null != request.getUid() && request.getUid() > 0) {
            queryWrapper.eq("uid", request.getUid());
        }
    }

    /**
     * 获取request的where条件
     *
     * @param queryWrapper QueryWrapper<StoreOrder> 表达式
     * @param request      StoreOrderSearchRequest 请求参数
     * @author Mr.Zhang
     * @since 2020-06-12
     */
    private void getRequestTimeWhere(QueryWrapper<StoreOrder> queryWrapper, StoreOrderSearchRequest request) {
        if (StringUtils.isNotBlank(request.getDateLimit())) {
            dateLimitUtilVo dateLimitUtilVo = DateUtil.getDateLimit(request.getDateLimit());
            queryWrapper.between("create_time", dateLimitUtilVo.getStartTime(), dateLimitUtilVo.getEndTime());
        }
    }

    //

    /**
     * h5 订单查询 where status 封装
     * 退款状态（0 未退款 1 申请中 2 已退款）
     * 订单状态（-1 : 申请退款 -2 : 退货成功 0：未支付，待发货；1：待收货；2：已收货，待评价；3：已完成；4：已取消；）
     *
     * @param queryWrapper 查询条件
     * @param status       状态
     */
    public void statusApiByWhere(LambdaQueryWrapper<StoreOrder> queryWrapper, int status) {
        switch (status) {
            case Constants.ORDER_STATUS_H5_UNPAID: // 未支付
                queryWrapper.eq(StoreOrder::getPaid, false);
                queryWrapper.eq(StoreOrder::getStatus, 0);
                queryWrapper.eq(StoreOrder::getRefundStatus, 0);
                break;
            case Constants.ORDER_STATUS_H5_NOT_SHIPPED: // 待发货
                queryWrapper.eq(StoreOrder::getPaid, true);
                queryWrapper.eq(StoreOrder::getStatus, 1);
                //queryWrapper.eq(StoreOrder::getRefundStatus, 0);
                break;
            case Constants.ORDER_STATUS_H5_SPIKE: // 待收货
                queryWrapper.eq(StoreOrder::getPaid, true);
                queryWrapper.eq(StoreOrder::getStatus, 2);
                //queryWrapper.eq(StoreOrder::getRefundStatus, 0);
                break;
            case Constants.ORDER_STATUS_H5_BARGAIN: //  待评价
                queryWrapper.eq(StoreOrder::getPaid, true);
                queryWrapper.eq(StoreOrder::getStatus, 3);
                //queryWrapper.eq(StoreOrder::getRefundStatus, 0);
                break;
            case Constants.ORDER_STATUS_H5_COMPLETE: // 已完成
                queryWrapper.eq(StoreOrder::getPaid, true);
                queryWrapper.eq(StoreOrder::getStatus, 4);
                //queryWrapper.eq(StoreOrder::getRefundStatus, 0);
                break;
            case Constants.ORDER_STATUS_H5_CANCEL: // 已取消
                queryWrapper.eq(StoreOrder::getPaid, false);
                queryWrapper.eq(StoreOrder::getStatus, 5);
                //queryWrapper.eq(StoreOrder::getRefundStatus, 0);
                break;
            case Constants.ORDER_STATUS_H5_REFUNDING: // 退款中
                queryWrapper.eq(StoreOrder::getPaid, true);
                queryWrapper.eq(StoreOrder::getRefundStatus, 1);
                break;
            case Constants.ORDER_STATUS_H5_REFUNDED: // 已退款
                queryWrapper.eq(StoreOrder::getPaid, true);
                queryWrapper.eq(StoreOrder::getRefundStatus, 2);//退货退款
                break;
            case Constants.ORDER_STATUS_H5_REFUND: // 退款
                queryWrapper.eq(StoreOrder::getPaid, true);
                queryWrapper.eq(StoreOrder::getRefundStatus, 3); //补偿性退款
                break;
        }
        queryWrapper.eq(StoreOrder::getIsDel, false);
        queryWrapper.eq(StoreOrder::getIsSystemDel, false);
    }

    /**
     * 根据订单状态获取where条件
     *
     * @param queryWrapper QueryWrapper<StoreOrder> 表达式
     * @param status       String 类型
     * @author Mr.Zhang
     * @since 2020-06-12
     */
    private void getStatusWhere(QueryWrapper<StoreOrder> queryWrapper, String status) {
        if (null == status) {
            return;
        }
        status = "all".equals(status) ? Constants.ORDER_STATUS_PAID : status;
        Integer orderStatus = null; //订单状态
        Integer paidStatus = null; //支付状态
        Integer refundStatus = null; //退款状态
        Integer deleteStatus = null; //删除状态
        Integer systemDeleteStatus = null; //系统删除
        Integer shippingType = null; //配送方式
        switch (status) {
            case Constants.ORDER_STATUS_UNPAID: //未支付
                paidStatus = 0; //支付状态
                orderStatus = 0; //订单状态
                refundStatus = 0; //退款状态
                deleteStatus = 0; //删除状态
                systemDeleteStatus = 0; //系统删除
                break;
            case Constants.ORDER_STATUS_NOT_SHIPPED: //未发货
                paidStatus = 1; //支付状态
                orderStatus = 1; //订单状态
                //refundStatus = 0; //退款状态
                shippingType = 1; //配送方式
                deleteStatus = 0; //删除状态
                systemDeleteStatus = 0; //系统删除
                break;
            case Constants.ORDER_STATUS_SPIKE: //待收货
                paidStatus = 1; //支付状态
                orderStatus = 2; //订单状态
                //refundStatus = 0; //退款状态
                deleteStatus = 0; //删除状态
                systemDeleteStatus = 0; //系统删除
                break;
            case Constants.ORDER_STATUS_BARGAIN: //待评价
                paidStatus = 1; //支付状态
                orderStatus = 3; //订单状态
                refundStatus = 0; //退款状态
                deleteStatus = 0; //删除状态
                systemDeleteStatus = 0; //系统删除
                break;
            case Constants.ORDER_STATUS_COMPLETE: //交易完成
                paidStatus = 1; //支付状态
                orderStatus = 4; //订单状态
                refundStatus = 0; //退款状态
                deleteStatus = 0; //删除状态
                systemDeleteStatus = 0; //系统删除
                break;
            case Constants.ORDER_STATUS_TOBE_WRITTEN_OFF: //待核销
                paidStatus = 1; //支付状态
                orderStatus = 0; //订单状态
                refundStatus = 0; //退款状态
                shippingType = 2; //配送方式
                deleteStatus = 0; //删除状态
                systemDeleteStatus = 0; //系统删除
                break;
            case Constants.ORDER_STATUS_REFUNDING: //退款中
                paidStatus = 1; //支付状态
                refundStatus = 1; //退款状态
                deleteStatus = 0; //删除状态
                systemDeleteStatus = 0; //系统删除
                break;
            case Constants.ORDER_STATUS_REFUNDED: //退货退款
                paidStatus = 1; //支付状态
                refundStatus = 2; //退款状态
                deleteStatus = 0; //删除状态
                systemDeleteStatus = 0; //系统删除
                break;
            case Constants.ORDER_STATUS_REFUNDED_PART: //补偿性退款
                paidStatus = 1; //支付状态
                refundStatus = 3; //退款状态
                deleteStatus = 0; //删除状态
                systemDeleteStatus = 0; //系统删除
                break;
            case Constants.ORDER_STATUS_DELETED: //已删除
                deleteStatus = 1; //删除状态
                systemDeleteStatus = 1; //系统删除,  未付款超时自动删除
                break;
            case Constants.ORDER_STATUS_PAID:  //已支付
                deleteStatus = 0; //删除状态
                systemDeleteStatus = 0; //系统删除
                queryWrapper.in("status", 1, 2, 3, 4);
            default:
                break;
        }
        if (paidStatus != null) {
            queryWrapper.eq("paid", paidStatus);
        }

        if (orderStatus != null) {
            queryWrapper.eq("status", orderStatus);
        }

        if (refundStatus != null) {
            queryWrapper.eq("refund_status", refundStatus);
        }

        if (shippingType != null) {
            queryWrapper.eq("shipping_type", shippingType);
        }

        if (deleteStatus != null) {
            if (deleteStatus == 1 && systemDeleteStatus == 1) {
                queryWrapper.and(i -> i.or().eq("is_del", 1).or().eq("is_system_del", 1));
            } else {
                queryWrapper.eq("is_del", deleteStatus);
            }
        }
    }


    /**
     * 获取订单状态
     *
     * @param storeOrder StoreOrder 订单信息
     * @author Mr.Zhang
     * @since 2020-06-12
     */
    @Override
    public Map<String, String> getStatus(StoreOrder storeOrder) {
        Map<String, String> map = new HashMap<>();
        map.put("key", "");
        map.put("value", "");
        if (null == storeOrder) {
            return map;
        }
        //未支付
        if (!storeOrder.getPaid()
                && storeOrder.getStatus() == 0
                && storeOrder.getRefundStatus() == 0
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_UNPAID);
            map.put("value", Constants.ORDER_STATUS_STR_UNPAID);
            return map;
        }
        //未发货
        if (storeOrder.getPaid()
                && storeOrder.getStatus() == 0
                && storeOrder.getRefundStatus() == 0
                && storeOrder.getShippingType() == 1
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_NOT_SHIPPED);
            map.put("value", Constants.ORDER_STATUS_STR_NOT_SHIPPED);
            return map;
        }
        //待收货
        if (storeOrder.getPaid()
                && storeOrder.getStatus() == 1
                && storeOrder.getRefundStatus() == 0
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_SPIKE);
            map.put("value", Constants.ORDER_STATUS_STR_SPIKE);
            return map;
        }
        //待评价
        if (storeOrder.getPaid()
                && storeOrder.getStatus() == 1
                && storeOrder.getRefundStatus() == 2
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_BARGAIN);
            map.put("value", Constants.ORDER_STATUS_STR_BARGAIN);
            return map;
        }
        //完成
        if (storeOrder.getPaid()
                && storeOrder.getStatus() == 3
                && storeOrder.getRefundStatus() == 0
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_COMPLETE);
            map.put("value", Constants.ORDER_STATUS_STR_COMPLETE);
            return map;
        }
        //订单已取消
        if (!storeOrder.getPaid()
                && storeOrder.getStatus() == 4
                && storeOrder.getRefundStatus() == 0
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_CANCEL);
            map.put("value", Constants.ORDER_STATUS_STR_CANCEL);
            return map;
        }
        //待核销
        if (storeOrder.getPaid()
                && storeOrder.getStatus() == 0
                && storeOrder.getRefundStatus() == 0
                && storeOrder.getShippingType() == 2
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_TOBE_WRITTEN_OFF);
            map.put("value", Constants.ORDER_STATUS_STR_TOBE_WRITTEN_OFF);
            return map;
        }

        //此处前端需要判断
        //退款中
        if (storeOrder.getPaid()
                && storeOrder.getRefundStatus() == 1
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_REFUNDING);
            map.put("value", Constants.ORDER_STATUS_STR_REFUNDING);
            return map;
        }
        //已退款
        if (storeOrder.getPaid()
                && storeOrder.getRefundStatus() == 2
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_REFUNDED);
            map.put("value", Constants.ORDER_STATUS_STR_REFUNDED);
        }
        //未发货
        if (storeOrder.getPaid()
                && storeOrder.getStatus() == 0
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_NOT_SHIPPED);
            map.put("value", Constants.ORDER_STATUS_STR_NOT_SHIPPED);
        }
        //待收货
        if (storeOrder.getPaid()
                && storeOrder.getStatus() == 1
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_SPIKE);
            map.put("value", Constants.ORDER_STATUS_STR_SPIKE);
        }
        //用户已收货
        if (storeOrder.getPaid()
                && storeOrder.getStatus() == 2
                && !storeOrder.getIsDel()
                && !storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_COMPLETE);
            map.put("value", Constants.ORDER_STATUS_STR_TAKE);
        }


        //已删除
        if (storeOrder.getIsDel() || storeOrder.getIsSystemDel()) {
            map.put("key", Constants.ORDER_STATUS_DELETED);
            map.put("value", Constants.ORDER_STATUS_STR_DELETED);
        }

        return map;
    }

    /**
     * 获取支付文字
     *
     * @param payType String 支付方式
     * @author Mr.Zhang
     * @since 2020-06-12
     */
    private String getPayType(String payType) {
        switch (payType) {
            case Constants.PAY_TYPE_WE_CHAT:
                return Constants.PAY_TYPE_STR_WE_CHAT;
            case Constants.PAY_TYPE_WE_CHAT_NATIVE:
                return Constants.PAY_TYPE_STR_WE_CHAT_NATIVE;
            case Constants.PAY_TYPE_YUE:
                return Constants.PAY_TYPE_STR_YUE;
            case Constants.PAY_TYPE_OFFLINE:
                return Constants.PAY_TYPE_STR_OFFLINE;
            case Constants.PAY_TYPE_ALI_PAY:
                return Constants.PAY_TYPE_STR_ALI_PAY;
            case Constants.PAY_TYPE_TMALL_PAY:
                return Constants.PAY_TYPE_STR_TMALL_PAY;
            case Constants.PAY_TYPE_HK_PAY:
                return Constants.PAY_TYPE_STR_HK_PAY;
            case Constants.PAY_TYPE_ORAGE_PAY:
                return Constants.PAY_TYPE_STR_ORAGE_PAY;
            case Constants.PAY_TYPE_ADAPAY_DEGREE:
                return Constants.PAY_TYPE_STR_ADAPAY_DEGREE;
            case Constants.PAY_TYPE_ADAPAY_CN:
                return Constants.PAY_TYPE_STR_ADAPAY_CN;
            default:
                return Constants.PAY_TYPE_STR_OTHER;
        }
    }

    private void subtractStock(StoreProduct storeProduct, TmallOrderInfoRequest tmallOrderInfo) {
        //buyer的商品 查询attrvalue
        StoreProductAttrValue apAttrValuePram = new StoreProductAttrValue();
        if (2 == storeProduct.getIsEurope()) {
            apAttrValuePram.setSourceSkuId(tmallOrderInfo.getProductInfo().getAttrInfo().getSourceSkuId());
            apAttrValuePram.setType(0);
        } else {
            apAttrValuePram.setBarCode(tmallOrderInfo.getProductInfo().getBarCode());
            apAttrValuePram.setSuk(tmallOrderInfo.getProductInfo().getAttrInfo().getSuk());
        }
        StoreProductAttrValue attrValue = storeProductAttrValueService.getByEntity(apAttrValuePram);
        if (null != attrValue) {
            log.info("天猫推送下单减attvalue库存,原来库存stock:{},需要减去库存cartNum:{}", attrValue.getStock(), tmallOrderInfo.getCartNum());
            int stock = attrValue.getStock() - tmallOrderInfo.getCartNum();
            attrValue.setStock(stock);
            storeProductAttrValueService.update(Wrappers.<StoreProductAttrValue>lambdaUpdate()
                    .set(StoreProductAttrValue::getStock, stock)
                    .eq(StoreProductAttrValue::getProductId, attrValue.getProductId())
                    .eq(StoreProductAttrValue::getSourceSkuId, attrValue.getSourceSkuId())
            );
//            storeProductAttrValueService.updateById(attrValue);
        }
    }

    private String getStatusStr(Integer status) {
        if (status == null) {
            return "";
        }
        OrderStatusEnum[] orderStatusEnums = OrderStatusEnum.values();
        for (OrderStatusEnum orderStatusEnum : orderStatusEnums) {
            if (orderStatusEnum.getCode().equals(status)) {
                return orderStatusEnum.getMsg();
            }
        }
        return "";
    }

    /**
     * 订单相关属性赋值
     *
     * @author daigb
     * @date: 2022-10-18 13:43
     */
    private CommonResult<Object> pushOrder(StoreOrder storeOrder, BarCodeEnum barCode, StoreOrderInfo info, Integer stock,
                           StoreProductAttrValue value, StoreProduct product, String ip, SystemAdmin systemAdmin, boolean checkStock,Integer platformAddressId) {
        //解析商品详情JSON
        StoreOrderInfoVo storeOrderInfoVo = new StoreOrderInfoVo();
        BeanUtils.copyProperties(info, storeOrderInfoVo, "info");
        storeOrderInfoVo.setInfo(JSON.parseObject(info.getInfo(), StoreCartResponse.class));
        storeOrderInfoVo.getInfo().setIsReply(storeProductReplyService.isReply(storeOrderInfoVo.getUnique(), "product", storeOrderInfoVo.getOrderId()).size());

        // 手动推送订单相关属性
        storeOrder.setSource(9);
        storeOrder.setPushOrderNo(info.getChildOrderNumber() + "-" + info.getId());
        if (info.getChildOrderNumber().contains("BY")){
            storeOrder.setPushOrderNo(info.getChildOrderNumber());
        }
        storeOrderInfoVo.setCheckStock(checkStock);
        storeOrderInfoVo.setId(info.getId());
        storeOrderInfoVo.getInfo().setCartNum(stock);
        storeOrderInfoVo.getInfo().getProductInfo().getAttrInfo().setProductId(product.getId());
        storeOrderInfoVo.getInfo().getProductInfo().getAttrInfo().setSourceSkuId(value.getSourceSkuId());
        storeOrderInfoVo.getInfo().getProductInfo().getAttrInfo().setPrice(value.getPrice());
        storeOrderInfoVo.getInfo().getProductInfo().getAttrInfo().setSourceCost(value.getSourceCost());
        storeOrderInfoVo.getInfo().getProductInfo().getAttrInfo().setOtPrice(value.getOtPrice());
        storeOrderInfoVo.getInfo().getProductInfo().getAttrInfo().setStock(stock);
        storeOrderInfoVo.getInfo().getProductInfo().getAttrInfo().setSuk(value.getSuk());
        storeOrderInfoVo.getInfo().getProductInfo().setImage(product.getImage() == null ? value.getImage() : product.getImage());
        storeOrderInfoVo.getInfo().getProductInfo().setStoreName(product.getStoreName());
        storeOrderInfoVo.getInfo().getProductInfo().setCateId(product.getCateId());
        storeOrderInfoVo.getInfo().getProductInfo().setBrandName(product.getBrandName());
        storeOrderInfoVo.getInfo().getProductInfo().setSupplierName(product.getSuppliersName());
        storeOrderInfoVo.getInfo().getProductInfo().setTempId(product.getTempId());
        storeOrderInfoVo.getInfo().getProductInfo().setIp(ip);
        storeOrderInfoVo.getInfo().getProductInfo().setUserName(systemAdmin.getRealName());
        storeOrderInfoVo.getInfo().getProductInfo().setUserId(systemAdmin.getId());
        storeOrderInfoVo.getInfo().getProductInfo().setId(value.getProductId());
        storeOrderInfoVo.getInfo().getProductInfo().setOtPrice(value.getOtPrice());
        storeOrderInfoVo.getInfo().getProductInfo().setIsEurope(product.getIsEurope() == 1 ? product.getConvertIsEurope() : product.getIsEurope());
        storeOrderInfoVo.getInfo().getProductInfo().setId(product.getId());
        storeOrderInfoVo.getInfo().getProductInfo().setKeyword(product.getKeyword());
        // Eur
        storeOrderInfoVo.getInfo().setSourceCostPrice(value.getSourceCost());
        storeOrderInfoVo.getInfo().getProductInfo().setBarCode(product.getBarCode());
        // GB
        storeOrderInfoVo.getInfo().getProductInfo().setSourceCost(value.getSourceCost());
        // LAVITA
        storeOrderInfoVo.setProductId(product.getId());
        storeOrderInfoVo.setExchangeRate(product.getExchangeRate());
        storeOrderInfoVo.setActualSupplierAddressId(platformAddressId);
        AbstractStoreOrderService storeOrderService = storeOrderFactory.getStoreOrderService(barCode);

        if(storeOrder.getOutOrderSource()!=0){   //外部来源订单

            log.info("--------------- 外部来源订单生成采购单, storeOrder: {} ---------------", storeOrder.getOrderId());

            StoreProductCartProductInfoResponse productInfo = storeOrderInfoVo.getInfo().getProductInfo();
            //新增采购单
            storeOrderFactory.insertPurchaseOrder(storeOrder, true, productInfo.getIsEurope());
            //新增采购商品
            storeOrderFactory.insertPurchaseGoods(storeOrderInfoVo, storeOrder, true, productInfo.getSupplierName() + "推送:成功", productInfo.getIsEurope() + "-" + storeOrder.getPushOrderNo());

        }else
        {
            //内部推送
            if (storeOrderService == null) {
                StoreProductCartProductInfoResponse productInfo = storeOrderInfoVo.getInfo().getProductInfo();
                //新增采购单
                storeOrderFactory.insertPurchaseOrder(storeOrder, true, productInfo.getIsEurope());
                //新增采购商品
                storeOrderFactory.insertPurchaseGoods(storeOrderInfoVo, storeOrder, true, productInfo.getSupplierName() + "推送:成功", productInfo.getIsEurope() + "-" + storeOrder.getPushOrderNo());
            } else {
                if (!manualPush) {
                    throw new CrmebException("供应商订单接口手动推送未开启!");
                }
                //2023.4.19 单独处理吉客云订单
                if(barCode.getCode()==8000){
                    log.info("--------------- 手动推送吉客云订单到速云供应商后台, barCode: {} ---------------", barCode.getCode());
                    StoreProductCartProductInfoResponse productInfo = storeOrderInfoVo.getInfo().getProductInfo();
                    //新增采购单
                    storeOrderFactory.insertPurchaseOrder(storeOrder, true, productInfo.getIsEurope());
                    //新增采购商品
                    storeOrderFactory.insertPurchaseGoods(storeOrderInfoVo, storeOrder, true, productInfo.getSupplierName() + "推送:成功", productInfo.getIsEurope() + "-" + storeOrder.getPushOrderNo());
                }else
                {
                    return storeOrderService.addChannelOrder(storeOrder, Collections.singletonList(storeOrderInfoVo));
                }

            }

        }
        return CommonResult.success();
//        storeOrderFactory.getStoreOrderService(barCode).addChannelOrder(storeOrder, Collections.singletonList(storeOrderInfoVo));
    }

    /**
     * @param id orderInfoId
     * @return boolean
     * @throws
     * @description 使用平台物流
     * @author lvmd
     * @date 2022/1/6 15:32
     */
    @Override
    public boolean useSystemDelivery(Integer id) {
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(id);
        if (Objects.isNull(storeOrderInfo)) {
            throw new CrmebException("该子订单不存在");
        }
        if (LogisticsTypeEnum.DEFAULT.getCode().equals(storeOrderInfo.getLogisticsType())) {
            StoreOrderInfo updateOrderInfo = new StoreOrderInfo();
            updateOrderInfo.setId(id);
            updateOrderInfo.setLogisticsType(LogisticsTypeEnum.PLATFORM.getCode());
            return storeOrderInfoService.updateById(updateOrderInfo);
        }
        throw new CrmebException("该订单已选择平台物流方式");
    }

    @Override
    public List<StoreOrder> getBacklogOrderQuantity() {
        return dao.getBacklogOrderQuantity();
    }

    @Override
    public boolean note(Integer id, String note) {
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(id);
        if (storeOrderInfo == null) {
            throw new CrmebException("该订单不存在");
        }
        int count = storeOrderStatusService.count(Wrappers.<StoreOrderStatus>lambdaQuery().eq(StoreOrderStatus::getChangeType, Constants.ORDER_PLATFORM_NOTE)
                .eq(StoreOrderStatus::getOid, storeOrderInfo.getOrderId()).eq(StoreOrderStatus::getOrderNumber, storeOrderInfo.getChildOrderNumber()));
        note = (count > 0 ? "修改备注:" : "订单备注:") + note;
        //订单备注
        storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_PLATFORM_NOTE, note);
        return true;
    }

    @Override
    public boolean refundApply(Integer id) {
        PurchaseGoods purchaseGoods = purchaseGoodsService.getById(id);
        if (purchaseGoods == null) {
            throw new CrmebException("该采购单不存在");
        }
        if (Objects.equals(purchaseGoods.getPushType(), 9)) {
            throw new CrmebException("该采购单为备份订单,请在商户后台操作");
        }
        if (!purchaseGoods.getPushStatus().equals("1")) {
            throw new CrmebException("该采购单推送失败状态");
        }
        purchaseGoods.setRefundStatus(1);
        purchaseGoodsService.updateById(purchaseGoods);
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(purchaseGoods.getStoreOrderInfoId());
        storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_SUPPLIER_LOG_REFUND, "平台申请退款");
        return true;
    }

    @Override
    public boolean refundApplyCancel(Integer id) {
        PurchaseGoods purchaseGoods = purchaseGoodsService.getById(id);
        if (purchaseGoods == null) {
            throw new CrmebException("该采购单不存在");
        }
        if (Objects.equals(purchaseGoods.getPushType(), 9)) {
            throw new CrmebException("该采购单为备份订单,请在商户后台操作");
        }
        if (purchaseGoods.getRefundStatus() != 1) {
            throw new CrmebException("该采购单不是申请退款状态");
        }
        purchaseGoods.setRefundStatus(0);
        purchaseGoodsService.updateById(purchaseGoods);
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(purchaseGoods.getStoreOrderInfoId());
        storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_SUPPLIER_LOG_REFUND, "平台取消申请退款");
        return true;
    }

    @Override
    public boolean confirmReceiptSupplier(Integer id, String reason) {
        PurchaseGoods purchaseGoods = purchaseGoodsService.getById(id);
        if (purchaseGoods == null) {
            throw new CrmebException("该采购单不存在");
        }
        if (Objects.equals(purchaseGoods.getPushType(), 9)) {
            throw new CrmebException("该采购单为备份订单,请在商户后台操作");
        }
        if (!purchaseGoods.getPushStatus().equals("1")) {
            throw new CrmebException("该采购单推送失败状态");
        }
        if (purchaseGoods.getRefundStatus() == 1) {
            throw new CrmebException("该采购单申请退款中");
        }
        if (purchaseGoods.getStatus() == 4) {
            throw new CrmebException("该采购单已完成");
        }
        if (purchaseGoods.getStatus() == -2) {
            throw new CrmebException("该采购单已退款");
        }
        if (purchaseGoods.getStatus() == 5) {
            throw new CrmebException("该采购单已取消");
        }
        purchaseGoods.setStatus(4);
        return purchaseGoodsService.updateById(purchaseGoods);
    }

    @Override
    public boolean cancelReceiptSupplier(Integer id, String clientIp) {
        PurchaseGoods purchaseGoods = purchaseGoodsService.getById(id);
        if (purchaseGoods == null) {
            throw new CrmebException("该采购单不存在");
        }
        if (Objects.equals(purchaseGoods.getPushType(), 9)) {
            throw new CrmebException("该采购单为备份订单,请在商户后台操作");
        }
        if (!Objects.equals(purchaseGoods.getPushStatus(), "1")) {
            throw new CrmebException("该采购单推送失败");
        }
        if (!purchaseGoods.getStatus().equals(OrderStatusEnum.CONFIRM.getCode())) {
            throw new CrmebException("该采购单不是待确认状态");
        }
        //查询订单所属供应商账户
        Supplier supplier = supplierService.getOne(Wrappers.<Supplier>lambdaQuery().eq(Supplier::getIsEurope, purchaseGoods.getChannelType()));
        ChannelMerchant channelMerchant = channelMerchantService.getOne(Wrappers.<ChannelMerchant>lambdaQuery().eq(ChannelMerchant::getChannelType, 3)
                .eq(ChannelMerchant::getSuppliersIds, "[" + supplier.getId() + "]"));
        if (channelMerchant == null) {
            throw new CrmebException("该供应商账户不存在");
        }
        SupplierInfo supplierInfo = channelMerchantService.getSupplierInfo(channelMerchant.getId());
        if (channelMerchant.getCreateTime().after(purchaseGoods.getCreateTime())) {
            throw new CrmebException("该采购单在供应商账户创建前生成，只读状态");
        }
        purchaseGoods.setStatus(OrderStatusEnum.CANCEL.getCode()).setRefundPrice(purchaseGoods.getGoodsPrice());
        boolean update = purchaseGoodsService.updateById(purchaseGoods);
        if (!update) {
            return false;
        }
        BigDecimal price = purchaseGoods.getGoodsPrice();
        if (Objects.nonNull(supplierInfo.getCurrency()) && !supplierInfo.getCurrency().equals(CurrencyEnum.CN)) {
            price = price.divide(purchaseGoods.getExchangeRate(), 2, RoundingMode.UP);
        }
        int adminId = systemAdminService.getAdminId();
        ChannelMerchantAccount merchant = new ChannelMerchantAccount();
        merchant.setMerId(channelMerchant.getId());
        merchant.setAccount(price.negate());
        merchant.setFreezeAccount(price);
        channelMerchantAccountService.calcMoney(merchant);
        accountFlowService.saveAccountFlow(channelMerchant.getId(), purchaseGoods.getId(), adminId, clientIp,
                AccountFlowTypeEnum.PRODUCT, price.negate(), null, null, "取消订单");
        return true;
    }

    /**
     * 功能描述: 海带云发货
     * @Param: [orderSn, dlyCodes, shipNos]
     * @Return: com.crmeb.core.common.CommonResult<java.lang.String>
     * @Author: wangzh
     * @Date: 2022/11/7 16:44
     */
    private void deliverGoods(String orderSn, String dlyCodes, String shipNos) throws Exception {
        DeliverGoods deliverGoods = new DeliverGoods();
        this.Login();
        ShippingApiInputDto inputDto = new ShippingApiInputDto();
        inputDto.setAccountId(accountId);
        inputDto.setMemberId(memberId);
        inputDto.setAppkey(appKey);
        inputDto.setUrl(domain);
        inputDto.setTimestamp(System.currentTimeMillis());
        inputDto.setSecret(secret);
        inputDto.setDlyCodes(dlyCodes);
        inputDto.setOrderSn(orderSn);
        inputDto.setShipNos(shipNos);
        String result = deliverGoods.deliverGoods(inputDto);
        log.info("--------------- 推送订单发货通知, 商户号: {}, 订单号: {}, 物流代码: {}, 返回信息: {} ---------------", "27", orderSn, dlyCodes, result);
    }

    /**
     * 功能描述: 海带云登陆
     * @Param: []
     * @Return: void
     * @Author: wangzh
     * @Date: 2022/11/7 16:45
     */
    private void Login() throws Exception {
        Map<String, String> map = new HashMap<>();
        map.put("appkey", appKey);
        map.put("secret", secret);
        map.put("username", username);
        map.put("password", MD5Util.MD5(password).toLowerCase());
        String params = HaidaiApiUtils.getApiParams(map, secret);
        String response = HaidaiApiUtils.doGet(login + "?" + params);
        JSONObject responseJson = JSONObject.parseObject(response);
        Integer result = responseJson.getInteger("result");
        if (result == 0) {
            log.error(responseJson.getString("message"));
            return;
        }
        JSONObject data = responseJson.getJSONObject("data");
        //member_id,accountId,token
        accountId = data.getString("accountId");
        memberId = data.getString("memberId");
        token = data.getString("token");
    }

    //海带云退单
    //退单原因列表（中文原因，字符要求完全一致）：1 身份证重复2 地址异常：地址中不能出现关于超市、母婴店、药店等类似的字眼3 地址超过购买限额4 联系方式有误5 报关失败6 收件人信息重复7 单证审核不通过8 身份证海关封号10 身份证号码错误20 身份证号码与姓名不对应30 身份验证失败40 地址不详50 地址重复60 联系方式超过购买限额70 身份信息超过购买限额80 订单商品缺货90 物流配送无法联系到收货人95 其它96 未上传身份证照片
    private String batchAddExceptionReply(String orderSn, Integer returnReason) throws Exception {
        DeliverGoods deliverGoods = new DeliverGoods();
        Login();
        BatchAddExceptionReplyApiInputDto inputDto = new BatchAddExceptionReplyApiInputDto();
        inputDto.setAccountId(accountId);
        inputDto.setMemberId(memberId);
        inputDto.setAppkey(appKey);
        inputDto.setUrl(domain);
        inputDto.setTimestamp(System.currentTimeMillis());
        inputDto.setSecret(secret);
        inputDto.setOrderSns(orderSn);
        inputDto.setReturnReason(returnReason);
        return deliverGoods.batchAddExceptionReply(inputDto);
    }

    /**
     * 功能描述: 海带云退单
     * 待加入业务
     * @Param: [args]
     * @Return: void
     * @Author: wangzh
     * @Date: 2022/11/10 15:27
     */
    @Override
    public void SeatentRefund() {
        try {
            // TODO 目前订单号、退款原因固定
            String result = batchAddExceptionReply("202211091981894147", ReturnReasonEnum.OTHER.getCode());
            //请求退单响应
            JSONObject response = JSONObject.parseObject(result);
            System.out.println(response);
            if (Objects.nonNull(response.getJSONObject("data"))){
                JSONObject data = response.getJSONObject("data");
                if (StringUtils.isNotBlank(data.getString("orderSn"))){
                    log.info("------------------- 海带云退单成功，订单号：{}，申请单号：{}，订单id：{}，售后单id：{} ------------------", data.getString("orderSn"), data.getString("applyNo"), data.getString("orderId"), data.getString("returnOrderId"));
                    // TODO 退单成功逻辑
                }
                if (StringUtils.isNotBlank(data.getString("alreadyReturnOrderIds"))){
                    // TODO 海带云退单失败处理流程
                    log.info("------------------- 海带云退单失败，原因：已经退单，订单号：{} -----------------", data.getString("alreadyReturnOrderIds"));
                } else if (StringUtils.isNotBlank(data.getString("errorOrderIds"))){
                    log.info("------------------- 海带云退单失败，原因：错误订单号，订单号：{} -----------------", data.getString("alreadyReturnOrderIds"));
                } else if (StringUtils.isNotBlank(data.getString("noGoods"))){
                    log.info("------------------- 海带云退单失败，原因：没有商品订单号，订单号：{} -----------------", data.getString("alreadyReturnOrderIds"));
                } else if (StringUtils.isNotBlank(data.getString("notAllowOrderIds"))){
                    log.info("------------------- 海带云退单失败，原因：不允许的订单号，订单号：{} -----------------", data.getString("alreadyReturnOrderIds"));
                } else if (StringUtils.isNotBlank(data.getString("unOrderIds"))){
                    log.info("------------------- 海带云退单失败，原因：非订单号的订单号，订单号“{} -----------------", data.getString("alreadyReturnOrderIds"));
                }
            } else {
                log.error("------------------ 海带云退单失败：{} ------------------", response.getString("message"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("-------------------- 海带云退单失败：{} --------------------", e.getMessage());
        }
    }

    /**
     * 功能描述: 批量发货
     * @Param: [request]
     * @Return: boolean
     * @Author: wangzh
     * @Date: 2023/3/29 14:58
     */
    @Override
    public OrderInfoDeliveryBatchUpload deliveryOrderBatch(List<DeliveryOrderBatchVo> request) {
        int total = request.size();
        OrderInfoDeliveryBatchUpload upload = new OrderInfoDeliveryBatchUpload();
        List<String> orderInfoIds = request.stream().map(DeliveryOrderBatchVo::getOrderId).collect(Collectors.toList());
        // 子订单列表
        List<StoreOrderInfo> orderInfos = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
                .in(StoreOrderInfo::getChildOrderNumber, orderInfoIds));
        // 查询子订单为空
        if (CollectionUtils.isEmpty(orderInfos)) {
            upload.setMsg("总计:" + request.size() + ",成功:" + 0 + ",失败:" + request.size());
            return upload;
        }
        // 子订单号映射
        Map<String, StoreOrderInfo> storeOrderInfoMap = orderInfos.stream().collect(Collectors.toMap(StoreOrderInfo::getChildOrderNumber, e -> e, (v1,v2) -> v2));
        // 订单id
        List<Integer> orderIds = orderInfos.stream().map(StoreOrderInfo::getOrderId).distinct().collect(Collectors.toList());
        List<StoreOrder> storeOrders = storeOrderService.listByIds(orderIds);
        Map<Integer, StoreOrder> storeOrderMap = storeOrders.stream().collect(Collectors.toMap(StoreOrder::getId, e -> e, (v1, v2) -> v2));
        List<DeliveryOrderBatchVo> failList = new ArrayList<>();
        // 失败数
        Integer failNumber = checkSendParams(request, failList, storeOrderInfoMap, storeOrderMap);
        request.removeAll(failList);
        request.forEach(deliveryOrderBatchVo -> {
            // 快递信息
            Express express = expressService.info(deliveryOrderBatchVo.getExpressId());
            String childOrderNumber = deliveryOrderBatchVo.getOrderId();
            // 子订单
            StoreOrderInfo storeOrderInfo = storeOrderInfoMap.get(childOrderNumber);
            // 主订单
            StoreOrder storeOrder = storeOrderMap.get(storeOrderInfo.getOrderId());
            if (Constants.ORDER_STATUS_H5_NOT_SHIPPED == storeOrderInfo.getStatus()) {
                storeOrderInfo.setStatus(Constants.ORDER_STATUS_H5_SPIKE);
                if (!storeOrder.getStatus().equals(Constants.ORDER_STATUS_H5_SPIKE)) {
                    storeOrder.setStatus(Constants.ORDER_STATUS_H5_SPIKE);
                    this.updateById(storeOrder);
                }
            }
            storeOrderInfoService.updateById(storeOrderInfo);
            StoreCartResponse storeCartResponse = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);
            List<OrderInfoDelivery> deliveries = orderInfoDeliveryService.list(Wrappers.<OrderInfoDelivery>lambdaQuery().eq(OrderInfoDelivery::getOrderInfoId, storeOrderInfo.getId()).eq(OrderInfoDelivery::getIsExchange, 0));
            // 发货
            if (deliveries.size() < 1) {
                Supplier supplier = supplierService.getById(storeOrderInfo.getActualSupplierId());
                if (Objects.nonNull(supplier)) {
                    purchaseGoodsService.update(Wrappers.<PurchaseGoods>lambdaUpdate().set(PurchaseGoods::getStatus, Constants.ORDER_STATUS_H5_SPIKE)
                            .eq(PurchaseGoods::getStoreOrderInfoId, storeOrderInfo.getId())
                            .eq(PurchaseGoods::getStatus, Constants.ORDER_STATUS_H5_NOT_SHIPPED)
                            .eq(PurchaseGoods::getGoodsSupplier, supplier.getSuppliersName()));
                }
            }
            String message = (deliveries.size() < 1 ? Constants.ORDER_LOG_MESSAGE_EXPRESS : Constants.ORDER_LOG_ADD_MESSAGE_EXPRESS)
                    .replace("{storeName}", storeCartResponse.getProductInfo().getStoreName()).replace("{suk}", storeCartResponse.getProductInfo().getAttrInfo().getSuk())
                    .replace("{channel}", "平台").replace("{deliveryName}", express.getName()).replace("{deliveryCode}", deliveryOrderBatchVo.getExpressCode());
            storeOrderStatusService.createLog(storeOrder.getId(), deliveryOrderBatchVo.getOrderId(), Constants.ORDER_LOG_EXPRESS, message);
            // 新增物流信息
            OrderInfoDeliveryRequest deliveryRequest = new OrderInfoDeliveryRequest();
            deliveryRequest.setOrderInfoId(storeOrderInfo.getId());
            deliveryRequest.setDeliveryCompany(express.getName());
            deliveryRequest.setDeliveryNumber(deliveryOrderBatchVo.getExpressCode());
            deliveryRequest.setName(deliveryOrderBatchVo.getName());
            deliveryRequest.setDeliveryCode(express.getCode());
            deliveryRequest.setPhone(deliveryOrderBatchVo.getPhone());
            deliveryRequest.setExpressId(deliveryOrderBatchVo.getExpressId());
            deliveryRequest.setLevel(1);
            deliveryRequest.setChannel(0);
            orderInfoDeliveryService.addDelivery(deliveryRequest);

            // 发货消息推送
            List<StoreOrderInfo> storeOrderInfos = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery().eq(StoreOrderInfo::getOrderId, storeOrder.getId()));
            List<Integer> infoIds = storeOrderInfos.stream().map(StoreOrderInfo::getId).collect(Collectors.toList());
            List<OrderInfoDelivery> orderInfoDeliveries = orderInfoDeliveryService.list(Wrappers.<OrderInfoDelivery>lambdaQuery()
                    .in(OrderInfoDelivery::getOrderInfoId, infoIds)
                    .last("GROUP BY order_info_id"));
            if (infoIds.size() == orderInfoDeliveries.size()) {
                List<OrderInfoDelivery> orderInfoDeliveries1 = orderInfoDeliveryService.list(Wrappers.<OrderInfoDelivery>lambdaQuery().in(OrderInfoDelivery::getOrderInfoId, infoIds));
                OutStoreOrderResponse outStoreOrderResponse = new OutStoreOrderResponse();
                outStoreOrderResponse.setOrderId(storeOrder.getOrderId());
                outStoreOrderResponse.setOrderInfoDeliverys(orderInfoDeliveries1);

                if (27 == storeOrder.getMerId()) {
                    if (ExpressTransition.getValueByCode(express.getCode()) == null) {
                        throw new CrmebException("海带云不支持该快递！");
                    }
                    try {
                        deliverGoods(storeOrder.getOrderId().split("OT")[1], ExpressTransition.getValueByCode(express.getCode()).getValue(), deliveryOrderBatchVo.getExpressCode());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    sendBackOrder(storeOrder.getMerId(), outStoreOrderResponse, storeOrder.getBackCount());
                }
            }
        });
        upload.setMsg("总计:"+ total +",成功:" + request.size() + ",失败:" + failNumber);
        return upload;
    }

    /**
     * 功能描述: 订单发货检查
     * @Param: [request, failList]
     * @Return: java.lang.Integer
     * @Author: wangzh
     * @Date: 2023/3/30 13:48
     */
    private Integer checkSendParams(List<DeliveryOrderBatchVo> request, List<DeliveryOrderBatchVo> failList, Map<String, StoreOrderInfo> storeOrderInfoMap, Map<Integer, StoreOrder> storeOrderMap) {
        request.forEach(deliveryOrderBatchVo -> {
            // 快递公司代码为空
            if (Objects.isNull(deliveryOrderBatchVo.getExpressId())) {
                failList.add(deliveryOrderBatchVo);
                return;
            }
            // 子订单号为空
            if (Objects.isNull(deliveryOrderBatchVo.getOrderId())) {
                failList.add(deliveryOrderBatchVo);
                return;
            }
            // 快递单号为空
            if (Objects.isNull(deliveryOrderBatchVo.getExpressCode())) {
                failList.add(deliveryOrderBatchVo);
                return;
            }
            // 分段名称
            if (Objects.isNull(deliveryOrderBatchVo.getName())) {
                failList.add(deliveryOrderBatchVo);
                return;
            }
            String childOrderNumber = deliveryOrderBatchVo.getOrderId();
            // 子订单
            StoreOrderInfo storeOrderInfo = storeOrderInfoMap.get(childOrderNumber);
            StoreOrder storeOrder = storeOrderMap.get(storeOrderInfo.getOrderId());
            // 主订单不是 待发货和待收货状态，不能发货
            if (!storeOrder.getStatus().equals(Constants.ORDER_STATUS_H5_SPIKE) && !storeOrder.getStatus().equals(Constants.ORDER_STATUS_H5_NOT_SHIPPED)) {
                failList.add(deliveryOrderBatchVo);
            }
        });
        return failList.size();
    }

    @Override
    public boolean cancelReceiptSupplierByApi(Integer id, String clientIp) {
        PurchaseGoods purchaseGoods = purchaseGoodsService.getById(id);
        if (purchaseGoods == null) {
            throw new CrmebException("该采购单不存在");
        }
        if (Objects.equals(purchaseGoods.getPushType(), 9)) {
            throw new CrmebException("该采购单为备份订单,请在商户后台操作");
        }
        if (!Objects.equals(purchaseGoods.getPushStatus(), "1")) {
            throw new CrmebException("该采购单推送失败");
        }
        if (!purchaseGoods.getStatus().equals(OrderStatusEnum.CONFIRM.getCode())) {
            throw new CrmebException("该采购单不是待确认状态");
        }
        //查询订单所属供应商账户
        Supplier supplier = supplierService.getOne(Wrappers.<Supplier>lambdaQuery().eq(Supplier::getIsEurope, purchaseGoods.getChannelType()));
        ChannelMerchant channelMerchant = channelMerchantService.getOne(Wrappers.<ChannelMerchant>lambdaQuery().eq(ChannelMerchant::getChannelType, 3)
                .eq(ChannelMerchant::getSuppliersIds, "[" + supplier.getId() + "]"));
        if (channelMerchant == null) {
            throw new CrmebException("该供应商账户不存在");
        }
        SupplierInfo supplierInfo = channelMerchantService.getSupplierInfo(channelMerchant.getId());
        if (channelMerchant.getCreateTime().after(purchaseGoods.getCreateTime())) {
            throw new CrmebException("该采购单在供应商账户创建前生成，只读状态");
        }

        //接口Api取消订单
        StoreOrder storeOrder  = storeOrderService.getByOrderId(purchaseGoods.getStoreOrderId());
        AbstractStoreOrderService storeOrderService = storeOrderFactory.getStoreOrderService(BarCodeEnum.IM);
        imStoreOrderService.cancelChannelOrderByApi(purchaseGoods);


        purchaseGoods.setStatus(OrderStatusEnum.CANCEL.getCode()).setRefundPrice(purchaseGoods.getGoodsPrice());
        boolean update = purchaseGoodsService.updateById(purchaseGoods);
        if (!update) {
            return false;
        }
        BigDecimal price = purchaseGoods.getGoodsPrice();
        if (Objects.nonNull(supplierInfo.getCurrency()) && !supplierInfo.getCurrency().equals(CurrencyEnum.CN)) {
            price = price.divide(purchaseGoods.getExchangeRate(), 2, RoundingMode.UP);
        }
        int adminId = systemAdminService.getAdminId();
        ChannelMerchantAccount merchant = new ChannelMerchantAccount();
        merchant.setMerId(channelMerchant.getId());
        merchant.setAccount(price.negate());
        merchant.setFreezeAccount(price);
        channelMerchantAccountService.calcMoney(merchant);
        accountFlowService.saveAccountFlow(channelMerchant.getId(), purchaseGoods.getId(), adminId, clientIp,
                AccountFlowTypeEnum.PRODUCT, price.negate(), null, null, "取消订单");
        return true;
    }

    /**
     * 订单手动推送
     */
    @Override
    public Boolean pushOrderTS(PushOrderRequest pushOrderRequest) {

        // 商品和订单详情
        StoreOrderInfo info = storeOrderInfoService.getById(pushOrderRequest.getInfoId());

        if(info==null){

            throw new CrmebException("订单为空!");

        }else
        {
            StoreCartResponse storeCartResponse = JSON.parseObject(info.getInfo(), StoreCartResponse.class);

            StoreProductAttrValue value = storeProductAttrValueService.getOne(Wrappers.<StoreProductAttrValue>lambdaQuery()
                                            .eq(StoreProductAttrValue::getSourceSkuId,storeCartResponse.getProductInfo().getAttrInfo().getSourceSkuId())
                                            .eq(StoreProductAttrValue::getProductId,storeCartResponse.getProductInfo().getAttrInfo().getProductId())
                    .last("LIMIT 1"));

            if (null == value) {
                throw new CrmebException("商品为空!");
            }

            // 订单信息
            StoreOrder order = this.getById(info.getOrderId());
            if (null == order) {
                throw new CrmebException("订单不存在!");
            }

            if (info.getIsPushTs() == true) {
                throw new CrmebException("该订单已经推送成功!");
            }

            StoreProduct product = storeProductService.getById(value.getProductId());

            traceSourceStoreOrderService.pushOrder(order, info, value, product, pushOrderRequest);

        }

        return true;
    }

    /**
     * 判断子订单是不是都已经确认完毕
     */
    @Override
    public Boolean isAllConfirm(StoreOrder storeOrder,Integer status) {

        if (null == storeOrder) {
            throw new CrmebException("订单为空!");
        }

        if (!status.equals(storeOrder.getStatus())) {
            throw new CrmebException("订单状态不一致!");
        }

        List<StoreOrderInfo> orderInfoList =
            storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
                            .eq(StoreOrderInfo::getOrderId, storeOrder.getId())
                            .eq(StoreOrderInfo::getStatus, status)
                            );

        if (orderInfoList.size() > 0) {  //相同的状态数据还存在
            return false;
        }

        return true;
    }

    @Override
    public Boolean changeSupplier(Integer id, String remark, Integer actualSupplierId, BigDecimal actualCost, BigDecimal actualCostEur, Integer stockAreaCode) {
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(id);
        checkStoreOrderInfo(storeOrderInfo);

        storeOrderInfo.setActualSupplierId(actualSupplierId);
        storeOrderInfo.setActualCost(actualCost);
        storeOrderInfo.setActualCostEur(actualCostEur);
        storeOrderInfo.setActualStockAreaCode(stockAreaCode);

        // 获取之前供应商信息，用于备用金返还
        Integer suppliersId;
        if (Objects.isNull(storeOrderInfo.getActualSupplierId())) {
            suppliersId = storeOrderInfo.getSuppliersId();
        } else {
            suppliersId = storeOrderInfo.getActualSupplierId();
        }

        // 变更供应商日志
        SystemAdmin systemAdmin = systemAdminService.getInfo();
        StringBuilder sb = new StringBuilder();
        Supplier supplier = supplierService.getById(actualSupplierId);
        if(systemAdmin != null){
            sb.append(systemAdmin.getRealName());
            sb.append("变更供应商推送订单商品: ");
            sb.append(storeOrderInfo.getStoreName());
            sb.append("到：");
            sb.append(supplier.getSuppliersName());
            sb.append("变更成功！");
        }

        if (StringUtils.isNotBlank(remark)) {
            sb.append(",备注：").append(remark);
        }

        boolean b = storeOrderInfoService.updateById(storeOrderInfo);
        if (b) {
            if (supplier != null) {
                purchaseGoodsService.update(Wrappers.<PurchaseGoods>lambdaUpdate()
                        .set(PurchaseGoods::getStatus, Constants.ORDER_STATUS_H5_CONFIRM)
                        .set(PurchaseGoods::getGoodsSupplier, supplier.getSuppliersName())
                        .set(PurchaseGoods::getChannelType, supplier.getIsEurope())
                        .set(PurchaseGoods::getGoodsPrice, actualCost)
                        .set(PurchaseGoods::getGoodsOtPrice, actualCostEur)
                        .eq(PurchaseGoods::getStoreOrderInfoId, storeOrderInfo.getId()));
            }
            //变更供应商记录备注
            storeOrderStatusService.createLog(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(), Constants.ORDER_CONFIRM_SUCCESS, sb.toString());
            // 变更供应商，备用金调整
            PurchaseGoods purchaseGoods = purchaseGoodsService.getOne(Wrappers.<PurchaseGoods>lambdaQuery().eq(PurchaseGoods::getStoreOrderInfoId, id).last("limit 1"));
            BigDecimal goodsPrice = purchaseGoods.getGoodsPrice();
            BigDecimal refundPrice = purchaseGoods.getRefundPrice();
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String ip = CrmebUtil.getClientIp(request);
            ChannelMerchant channelMerchant = channelMerchantService.getOne(Wrappers.<ChannelMerchant>lambdaQuery()
                    .eq(ChannelMerchant::getChannelType, 3)
                    .eq(ChannelMerchant::getSuppliersIds, "[" + actualSupplierId + "]"));
            // 变更后供应商结算
            // 使用最终成本价结算
            purchaseGoods.setGoodsPrice(actualCost);
            reserveMoneyDetailService.calcReserveMoney(purchaseGoods, Objects.isNull(channelMerchant.getCurrency()) ? null : CurrencyEnum.valueOf(channelMerchant.getCurrency()), channelMerchant.getId(), purchaseGoods.getId(), ip);
            // 之前的供应商信息
            ChannelMerchant channelMerchant1 = channelMerchantService.getOne(Wrappers.<ChannelMerchant>lambdaQuery()
                    .eq(ChannelMerchant::getChannelType, 3)
                    .eq(ChannelMerchant::getSuppliersIds, "[" + suppliersId + "]"));
            // 自动结算过 退备用金 否则不退
            if (reserveMoneyDetailService.checkSupplierAutoSettlement(purchaseGoods.getId(), channelMerchant1.getId())) {
                purchaseGoods.setGoodsPrice(refundPrice);
                purchaseGoods.setRefundPrice(goodsPrice);
                reserveMoneyDetailService.calcReserveMoney(purchaseGoods, Objects.isNull(channelMerchant1.getCurrency()) ? null : CurrencyEnum.valueOf(channelMerchant.getCurrency()), channelMerchant1.getId(), purchaseGoods.getId(), ip);
            }
        }

        return b;
    }

    public Boolean CheckJkyItemSyn(JkyItemSynRequest jkyItemSynRequest) {

        StoreProductAttrValue storeProductAttrValue = storeProductAttrValueService.getOne(Wrappers.<StoreProductAttrValue>lambdaQuery()
                .eq(StoreProductAttrValue::getSelfSourceSkuId,jkyItemSynRequest.getContent().getItem().getBarCode())
                .gt(StoreProductAttrValue::getStock, 0)
                .last("LIMIT 1"));

        if (null == storeProductAttrValue) {
           return false;
        }

        // 校验商品
        StoreProduct  storeProduct = storeProductService.getById(storeProductAttrValue.getProductId());

        if(storeProduct.getIsShow()){
            return true;
        }else
        {
            return false;
        }

    }

    /**
     * 功能描述: 吉客云回传
     * @Param: [orderSn, dlyCodes, shipNos]
     * @Return: com.crmeb.core.common.CommonResult<java.lang.String>
     * @Author:
     * @Date: 2023/5/12 16:44
     */
    public void JkyDeliverGoods(StoreOrder storeOrder,StoreOrderInfo storeOrderInfo) throws Exception {

        String orderSn = storeOrder.getOrderId().split("OT")[1];

        List<OrderInfoDelivery> orderInfoDeliverys = orderInfoDeliveryService.list(Wrappers.<OrderInfoDelivery>lambdaQuery()
                .eq(OrderInfoDelivery::getOrderInfoId, storeOrderInfo.getId())
        );

        JkyDeliveryOrderConfirmDTO jkyDeliveryOrderConfirmDTO = new JkyDeliveryOrderConfirmDTO();

        JkyDeliveryOrderConfirmDTO.deliveryOrder deliveryOrder = new JkyDeliveryOrderConfirmDTO.deliveryOrder();

        //设置 deliveryOrder
        deliveryOrder.setDeliveryOrderCode(orderSn);
//        deliveryOrder.setWarehouseCode(orderSn);
        deliveryOrder.setOrderType("JYCK");

        //设置packages
        Express express;

        List<JkyDeliveryOrderConfirmDTO.Packages>  packageList =  new ArrayList<>();

        for(OrderInfoDelivery orderInfoDelivery : orderInfoDeliverys){

            JkyDeliveryOrderConfirmDTO.Packages packageData = new JkyDeliveryOrderConfirmDTO.Packages();
            JkyDeliveryOrderConfirmDTO.Item item = new JkyDeliveryOrderConfirmDTO.Item();
            List<JkyDeliveryOrderConfirmDTO.Item> itemList =  new ArrayList<>();

            StoreCartResponse storeCartResponse = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);

            express = expressService.info(orderInfoDelivery.getExpressId());

            if(Objects.nonNull(express) && Objects.nonNull(express.getJkyExpressCode())){

                packageData.setExpressCode(orderInfoDelivery.getDeliveryNumber());
                packageData.setLogisticsCode(express.getJkyExpressCode());
                packageData.setLogisticsName(orderInfoDelivery.getDeliveryCompany());

                //商品信息
                item.setItemCode(storeCartResponse.getProductInfo().getAttrInfo().getSelfSourceSkuId());
                item.setItemId(storeCartResponse.getProductInfo().getAttrInfo().getSelfSourceSkuId());
                item.setQuantity(storeCartResponse.getCartNum());
                itemList.add(item);

                packageData.setItems(itemList);
                packageList.add(packageData);

            }else
            {
                throw new CrmebException("吉客云的快递code为空！请先配置！");
            }
        }

        jkyDeliveryOrderConfirmDTO.setDeliveryOrder(deliveryOrder);
        jkyDeliveryOrderConfirmDTO.setPackages(packageList);

        JkyOrderResponse jkyOrderResponse = JackyunOpenHttpUtils.JkyDeliveryOrderConfirm(jkyDeliveryOrderConfirmDTO);

        if("success".equals(jkyOrderResponse.getFlag())){
            storeOrder.setDeliverFlg(1);
            storeOrder.setDeliveryNoticeMsg("发货回传成功");
            this.updateById(storeOrder);
        }else
        {
            storeOrder.setDeliverFlg(9);
            storeOrder.setDeliveryNoticeMsg(jkyOrderResponse.getMessage());
            this.updateById(storeOrder);
        }

    }

    @Override
    public Boolean jkyCancelOrder(Integer id) {
        StoreOrder storeOrder = getById(id);
        if (null == storeOrder) {
            throw new CrmebException("没有找到相关订单信息!");
        }

        //采购单判断
        int count = purchaseOrderDao.selectCount(Wrappers.<PurchaseOrder>lambdaQuery()
                .eq(PurchaseOrder::getStoreOrderId, storeOrder.getOrderId())
                .ne(PurchaseOrder::getOrderType, 6)
        );
        if (count > 0) {
            throw new CrmebException("订单已经推送无法取消！");

        }

//        if (!storeOrder.getStatus().equals(OrderStatusEnum.UNPAID.getCode()) && !storeOrder.getStatus().equals(OrderStatusEnum.VERIFY.getCode())) {
//            throw new CrmebException("订单状态异常");
//        }

        storeOrderStatusService.createLog(storeOrder.getId(), storeOrder.getOrderId(), "cancel_order", "吉客云平台取消订单");
        //取消订单返还
//        cancelUserIntegral(storeOrder, userService.getById(storeOrder.getUid()), "平台取消订单");
        //取消前状态
        Integer status = storeOrder.getStatus();
        //已取消
        storeOrder.setStatus(OrderStatusEnum.CANCEL.getCode());
        //回滚使用积分
        if (storeOrder.getUseIntegral() > 0) {
            storeOrder.setBackIntegral(storeOrder.getUseIntegral());
            storeOrder.setUseIntegral(0);
        }
        boolean update = updateById(storeOrder);
        //回滚优惠券
//        storeCouponUserService.rollbackByCancelOrder(storeOrder);
        if (update && !Objects.equals(status, OrderStatusEnum.VERIFY.getCode())) {
            //取消子订单
            storeOrderInfoService.update(Wrappers.lambdaUpdate(StoreOrderInfo.class).eq(StoreOrderInfo::getOrderId, storeOrder.getId())
                    .set(StoreOrderInfo::getStatus, OrderStatusEnum.CANCEL.getCode()));
            storeOrderTaskService.rollbackStock(storeOrder);
        }
        return update;
    }

    /**
     * 功能描述: 确认订单检查订单状态
     * @Param: [id]
     * @Return: void
     * @Author: wangzh
     * @Date: 2023/5/22 14:22
     */
    private void checkStoreOrderInfo(StoreOrderInfo storeOrderInfo) {
        if (storeOrderInfo == null) {
            throw new CrmebException("该子订单不存在");
        }
        if (storeOrderInfo.getAbnormal() == 1) {
            throw new CrmebException("该订单为异常订单");
        }
        if (!storeOrderInfo.getStatus().equals(OrderStatusEnum.CONFIRM.getCode())) {
            throw new CrmebException("该子订单状态不是待确认状态");
        }
        if (null == storeOrderInfo.getAutonomous()) {
            throw new CrmebException("该订单等待商户确认发货方式");
        }
        if (1 == storeOrderInfo.getAutonomous()) {
            throw new CrmebException("该订单商户自主发货");
        }
        if (storeOrderInfo.getIsEurope() == 1) {
            throw new CrmebException("该子订单商品是商户自建商品");
        }
    }
}

